Skip to main content

News

Topic: Programming a map animation (Read 4528 times) previous topic - next topic

Programming a map animation
  Is a loop involving Tileset (x,y, , tileindex, layer) the best way to show changes in a map layer or should I use a surface or something else? I have a simple sprite that moves across the screen leaving marks behind it. The layer is transparent over a base layer background and then as the sprite moves forward, the tiles for the marks are set in place. Would it be too blocky an entire tile at a time? I will add some pics I have soon.

  • Last Edit: June 04, 2013, 11:29:02 am by laserblue

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: Programming a map animation
Reply #1
Huh, you're creating a farming simulator - that's neat. Are you going to stay with those lines? Because what you can do is use the Line() function in a map render script. You will need to indicate a start position and an end position as the tractor moves.

Code: (javascript) [Select]

var Points = [];      // the tilling field points.
var black = CreateColor(0, 0, 0); // line color.

function RenderLines()
{
  for (var i = 1; i < 0 g_lines.length; ++i) {
     Line(Points[i-1].x, Points[i]-1.y, Points[i].x, Points[i].y, black);
  }
}

var enter_down;  // handles a single key press.
var mode = false; // are we in tilling mode?
function UpdateLines()
{
  var key_down = IsKeyPressed(KEY_ENTER);

  if (key_down && !key_last) {
    if (!mode) {
      Points[0] = { x: GetPersonX("tractor"), y: GetPersonY("tractor")-4 };
      Points[1] = { x: GetPersonX("tractor"), y: GetPersonY("tractor")-4 };
      Points[2] = { x: GetPersonX("tractor"), y: GetPersonY("tractor")+4 };
      Points[3] = { x: GetPersonX("tractor"), y: GetPersonY("tractor")+4 };
    }
    var mode = !mode;
  }

  if (mode) {
      Points[1] = { x: GetPersonX("tractor"), y: GetPersonY("tractor")-4 };
      Points[3] = { x: GetPersonX("tractor"), y: GetPersonY("tractor")+4 };
  }

  key_last = key_down;
}

function game()
{
  // ...

  SetUpdateScript("UpdateLines()");
  SetRenderScript("RenderLines()");
  
  // ...

  MapEngine("my_map.rmp", 60);
}


That's how you can do that. Pressing enter puts the code into tilling mode, then it draws lines that indicates the tilling. Now if you want it to do something else, it's just a matter of not drawing the lines, but images instead. I hope you get all that, render scripts and update scripts are very powerful Sphere functions.

Edit: thanks for catching that Alpha123
  • Last Edit: May 13, 2013, 03:42:51 pm by Radnen
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

Re: Programming a map animation
Reply #2
I'd probably do this by SetTile()ing some tiles on a separate layer above the ground layer. This is more flexible than just using Line(), although also a bit more complicated.

Basically it would look like this:
Start with a ground layer and a completely transparent layer above that.
As the tractor moves, set the tile behind the tractor to a tile that is completely transparent except for the lines.
If the tractor turns, use a special turn tile instead.
Keep a vector of the tractor's current direction and use floor(tractorX / tileWidth) - directionX, floor(tractorY / tileHeight) - directionY to get the tile behind it. (Where directionX is 1 if the tractor is going east, -1 for west, directionY is 1 for south and -1 for north.)
When the direction vector changes, change the tile that you're using for the lines.

EDIT: Radnen, I think you mean
Code: (javascript) [Select]
SetUpdateScript("UpdateLines()");
SetRenderScript("RenderLines()");

instead of
Code: (javascript) [Select]
SetUpdateScript(UpdateLines());
SetRenderScript(RenderLines());

which will parse and run but not at all do what you expect.
  • Last Edit: May 13, 2013, 02:36:31 pm by alpha123

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: Programming a map animation
Reply #3
Alpha123: I think that's what he meant by "blocky": the tiles will turn on as you move per tile. My line idea was to try and show him how to use an input to toggle a behavior and to draw lines as the tractor moves. Of course, if he no longer decides to use lines then my idea will need updating.
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

Re: Programming a map animation
Reply #4
Ah that's true, yours will look a lot smoother. The problem is handling the tractor turning.

Re: Programming a map animation
Reply #5
 :D It is NOT a FARMING Simulation.  :D Agricultural, maybe. I might add some sweaty hoers with red dew rags later as extras in the background as a tribute to Radnen's Pioneer. It's going to be a boring, non-violent, possibly educational, fantasy adventure game with puzzles as a Walter Mitty type character works at the Corn Breeding Research Station. "Une autre carte monsieur?"  First I am making static illustrations for a job write up and then animated scenes. I fixed up my tractor a bit yesterday so things are more symmetrical and rectangular. Still nowhere close to a 3D SimTractor. The tractor is marking aisles/paths for the Inbreeding Nursery ranges with a 2-disk marker implement. It's zoomed out to 0.5 scale. The beige bits are wooden stakes. Not sure top-down tractor perspective best. Easiest.
    Thank you everyone for your replies. You understood me Radnen. Thank you very much for posting that code. As soon as I figure out the syntax error I will try it out and post a video or stills. Missing ;? Missing ) ?  Bugs!
     I'll also try the tile by tile idea for comparison. I'm leaving the turning Spriteset frames and animation  for later. 
   

Re: Programming a map animation
Reply #6
Well that's an original concept lol. These simulator games or "so-and-so tycoon" games can get really addictive :D

Re: Programming a map animation
Reply #7
  I need some tutorial material on the animation loop and use of RenderScript, SetRenderScript and SetUpdateScript functions I can't get the RenderLines() code to work. I keep getting either a missing ; or ) syntax error. Line(x1, y1, x2, y2, color) works when values are inserted but the line runs through my stakes rather than behind them. I'm starting to wonder about using LineSeries, PointSeries and Surface objects. I'm looking through Sphere code but have not found some example code yet.
The code below using SetTile(x,y, layer, tile_index)) draws three sets of lines at a decent speed with wait(100) but is jerky at wait(500).  I tried putting it into a RenderLines() function but I got "Map engine not running" problems or missing } syntax errors.
    I also have tried putting in code for the tractor sprite movement. With AttachInput() it works ok but I want it to move by itself. When I add GetTileWidth() *5; it just runs off the screen instead of stopping after the fifth tile and I could not get it to synchonize with the lines very well but a speed of 5 was close. I have since revised the code by adding the move command between each line set loop and it looks good enough but is very linear, clunky coding. I need to learn more about the QueuePersonScript and QueuePersonCommand functions and where to put them in my code.

Code: (javascript) [Select]
// Show all stakes in untilled field - zoom out 
DetachCamera();

// Set view to show stakes on both sides
SetCameraX(600);
  SetCameraY(300);
 
 
 
  // Zoom view out to see all stakes
  SetLayerScaleFactorX(0, 0.5);
  SetLayerScaleFactorY(0, 0.5);
  SetLayerScaleFactorX(1, 0.5);
  SetLayerScaleFactorY(1, 0.5);
  SetLayerScaleFactorX(2, 0.5);
  SetLayerScaleFactorY(2, 0.5);
  SetLayerScaleFactorX(3, 0.5);
  SetLayerScaleFactorY(3, 0.5);
  SetLayerScaleFactorX(4, 0.5);
  SetLayerScaleFactorY(4, 0.5);
 
  // Show desired layers - 0 is base soil, 3 is stakes, 4 is tractor
  SetLayerVisible(0, true);
  SetLayerVisible(1, false);
  SetLayerVisible(2, false);
  SetLayerVisible(3, true);
  SetLayerVisible(4, true);
  SetLayerVisible(5, false);
 
  RenderMap();
    FlipScreen();
  wait(5000);

FadeOut(1000);

// Show marking of aisles/paths in field with tractor
  DetachCamera();
CreatePerson("George",'TopTractor.rss',true);
SetPersonLayer("George", 4);
SetPersonDirection("George","east");

SetPersonVisible("George", true);
 
SetPersonX("George", 50);
  SetPersonY("George", 600);


    
  SetLayerScaleFactorX(0, 0.5);
  SetLayerScaleFactorY(0, 0.5);
 
  SetLayerScaleFactorX(1, 0.5);
  SetLayerScaleFactorY(1, 0.5);
 
  SetLayerScaleFactorX(2, 0.5);
  SetLayerScaleFactorY(2, 0.5);
 
  SetLayerScaleFactorX(3, 0.5);
  SetLayerScaleFactorY(3, 0.5);
 
  SetLayerScaleFactorX(4, 0.5);
  SetLayerScaleFactorY(4, 0.5);
 

   //RenderLines();
  RenderMap();
   FlipScreen();
   wait(500)

   

  // Change map line tiles as sprite moves to right
 
    // Line(100, 600, 500, 600, black);
 
  CreatePerson("GeorgeEast2",'TopTractor.rss',true);
SetPersonLayer("GeorgeEast2", 4);
SetPersonDirection("GeorgeEast2","west");
SetPersonX("GeorgeEast2", 50);
  SetPersonY("GeorgeEast2", 152);
SetPersonVisible("GeorgeEast2", false);
  
   CreatePerson("GeorgeWest",'TopTractor.rss',true);
SetPersonLayer("GeorgeWest", 4);
SetPersonDirection("GeorgeWest","west");
SetPersonX("GeorgeWest", 700);
  SetPersonY("GeorgeWest", 376);
SetPersonVisible("GeorgeWest", false);
  
  
  for (i= 3; i< 46; i++) {
  SetTile(i, 37, 1, 26);
  SetTile(i, 38, 1, 25);
   
    SetPersonSpeed("George", 16);
    SetPersonDirection("George", "east");
    QueuePersonCommand("George", COMMAND_MOVE_EAST, true);
  
   
   // SetTile(3, 37, 1, 26) - first tile of upper line for first range as example
 
  // Tile positions for all lines
  // Bottom Lines: (3.37) to (46,37) and (3,38) to (46,38)
  // Middle Lines: (3,23) to (46,23) and (3,24) to (46,24)
  // Top Lines:    (3,9) to (46,9) and (3,10) to (46,10)
  
  SetLayerVisible(0, true);
  SetLayerVisible(1, true);
  SetLayerVisible(2, false);
  SetLayerVisible(3, true);
  SetLayerVisible(4, true);
 
  
  RenderMap();
  FlipScreen();
  wait(100);
  
      }
  SetPersonVisible("George", false);

for (k= 46; k> 3; k--) {
  SetTile(k, 23, 1, 26);
  SetTile(k, 24, 1, 25);
  
   SetPersonVisible("GeorgeWest", true);
   SetPersonSpeed("GeorgeWest", 17);
   QueuePersonCommand("GeorgeWest", COMMAND_MOVE_WEST, true);
  
  
  RenderMap();
   FlipScreen();
   wait(100);
    }  

   SetPersonVisible("GeorgeWest", false);
for (k= 3; k< 46; k++) {
  SetTile(k, 9, 1, 26);
  SetTile(k, 10, 1, 25);
   
    SetPersonVisible("GeorgeEast2", true);
    SetPersonSpeed("GeorgeEast2", 16);
    SetPersonDirection("GeorgeEast2", "east");
    QueuePersonCommand("GeorgeEast2", COMMAND_MOVE_EAST, true);
 
  
  RenderMap();
   FlipScreen();
    wait(100); 
       }   
    
     SetPersonVisible("GeorgeEast2", false);
     
   
  wait(1000)
  
SetLayerVisible(3, false);
  RenderMap();
    FlipScreen();
  wait(1000);
  • Last Edit: May 31, 2013, 11:06:47 am by laserblue

  • N E O
  • [*][*][*][*][*]
  • Administrator
  • Senior Administrator
Re: Programming a map animation
Reply #8
Your code calls UpdateMapEngine() between RenderMap() and FlipScreen(). If you make updates before RenderMap you should UpdateMapEngine before RenderMap; if you make updates after RenderMap, the updates AND UpdateMapEngine should technically be after FlipScreen so that the updated map is ready for the next RenderMap call.

Re: Programming a map animation
Reply #9
 Thanks NEO. I don't understand yet, exactly how the animation loop works. Most of the available code has RenderScript(); then FlipScreen(); and I just threw UpdateMapEngine(); in because it sounded good. I was thinking RenderMap would draw the map to the back buffer, UpdateMapEngine would update the map engine with any other info and then Flipscreen would show my map.  Commenting out all the UpdateMapEngine lines didn't affect anything probably because I have no applicable map entities to update. I thought the Sprite might be a map entity but I guess not. I'm working on understanding the coding VERY SLOWLY. Thank you for your patience and understanding.
  • Last Edit: May 30, 2013, 12:58:45 pm by laserblue

  • N E O
  • [*][*][*][*][*]
  • Administrator
  • Senior Administrator
Re: Programming a map animation
Reply #10
Your understanding is so far correct: RenderMap does indeed draw the current map to the back buffer, UpdateMapEngine force-updates the map engine one step. It's that RenderMap does NOT update the map before blitting to the back buffer, so all the camera setting and layer updating don't take effect before the map is buffered.

If anything changes on a map, the map engine must be updated either manually or automatically or else RenderMap won't see the updates in time.

Re: Programming a map animation
Reply #11
Here is a video of what I am working towards
http://www.youtube.com/watch?v=BxIMZLlFiS0&feature=c4-overview&list=UU7OaeQ60hSBQ80yjGsXrV8A.

I used SetTile to change tiles from unmarked to marked. It was difficult to match the speeds of the lined tiles and the sprite especially for the second set of lines. I am now backing up and trying to get the Lines function to work with UpdateScript and RenderScript. So far I keep getting a syntax error stating that a semicolon is missing after the for loop.

Code: [Select]
 for (var i= 0; i<0 g_lines.length; ++i; ) {
     Line(Points[i-1].x, Points[i]-1.y, Points[i].x, Points[i].y, black); ] 
         }
    }

   I put SetUpdateScript and SetRenderScript  in main.js. I call my Intro function and declare a Points array and a colour for the pixels making up the line. I have a RenderLines function and an UpdateLines function. In my intro function I am going to have a RenderMap, FlipScreen, THEN UpdateMap (?). 
  
  • Last Edit: September 23, 2013, 12:23:35 pm by laserblue

  • N E O
  • [*][*][*][*][*]
  • Administrator
  • Senior Administrator
Re: Programming a map animation
Reply #12
Check the y coordinate of the first point (the -1 looks to be outside the [ ]) and remove the ] at the end of the line.

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: Programming a map animation
Reply #13
Also remove that last semicolon in the for clause, and there appears to be an extra close brace.
miniSphere 5.0b4 (stable: 4.8.8) - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enourmous man eating pigs ~Rhuan

Re: Programming a map animation
Reply #14
Code: [Select]
 
for (var i = 1; i < g_lines.length; i++) {
     Line(Points[i-1].x, Points[i-1].y, Points[i].x, Points[i].y, black);      
}


That looks more like what I would expect.