Articles Archive
Articles Search
Director Wiki
 

Building a Game: Sprite Invaders: Part 1

March 7, 2000
by Gary Rosenzweig

This week we will begin a three-part series on how to create a basic game in Lingo. The game is called Sprite Invaders. Complete code for this game can be found in my new book, "Advanced Lingo for Games," which should be available by the time you read this.

The game Sprite Invaders involves several rows of invading aliens. These guys aren't too bright, so they invade by moving from side to side. When they hit a side of the screen, they reverse horizontal direction and descend toward the ground by a bit.

Figure 1 shows the invaders on the screen. They will move to the right until the right-most column of invaders gets close to the edge, and then they will drop down a few pixels and start moving to the left. They will continue to move to the left until the left-most column of invaders gets close to the left edge, where there will be another vertical drop and the invaders start moving back to the right.

For this installment of the Lingo Lounge we will figure out how to make the invaders move like this. In the next two articles, we will add your ship, allow you to fire at the invaders, allow them to fire back at you, and finish off the game.

Making the invaders move back and forth and down is not as simple as it seems. We can easily attach a behavior to each invader that makes it move in one direction. This same behavior can detect when that invader is close to the sides of the screen. At that point the invader must instruct ALL of the other invaders to drop and start moving in the opposite direction.

This message to change direction cannot come at a time when some invaders have completed their move for the frame and others have not. It must come when all the invaders are done moving for the frame. To accomplish this, we will use a combination of the on enterFrame handler and the on exitFrame handler.

The on enterFrame handler in a behavior runs just after the frame is drawn, but, of course, before any on exitFrame handlers get run. Thus, we can trigger the change of direction here.

The behavior for the moving invaders starts off by getting the speed of the invader from a parameter set when the behavior is attached to the sprite.

property pSpeed
property pDirection
property pMemNum
property pOrigLoc
on getPropertyDescriptionList me
  list = [:]
  addProp list, #pSpeed, [#comment: "Speed", #format: #integer, ¬
    #default: 2]
  return list
end

When the sprite begins, the original location of the invader is recorded, as well as the member number. The pDirection property is either 1 if the sprites are moving to the right, or -1 if to the left.

on beginSprite me 
  pOrigLoc = sprite(me.spriteNum).loc
  pMemNum = sprite(me.spriteNum).memberNum
  pDirection = 1 -- start moving to right
end

When each frame is done, the sprite is repositioned for the next frame. The horizontal location of the sprite is changed. Then, if the sprite is moving to the right, a check is made to see if it is within 20 pixels of the right side of the screen. If the sprite is moving to the left, a check is made to see if the sprite is within 20 pixels of the left side. In both of these cases, a message is sent to the frame behavior to tell it that it is time to switch directions.

Another thing that the on exitFrame handler does is to switch the member number of the sprite. It will switch it between its original member and the very next one in the cast. This will create a "marching" effect as the sprites move.

on exitFrame me
  -- move
  x = sprite(me.spriteNum).locH
  x = x + pDirection*pSpeed
  sprite(me.spriteNum).locH  = x    
  
  -- hit a wall?
  if pDirection > 0 and x > (the stage).rect.width-20 then
    sendSprite(0,#hitWall)
  else if pDirection < 0 and x < 20 then
    sendSprite(0,#hitWall)
  end if
  
  -- toggle to other member to create animation
  if sprite(me.spriteNum).memberNum = pMemNum then
    sprite(me.spriteNum).memberNum = pMemNum + 1
  else
    sprite(me.spriteNum).memberNum = pMemNum
  end if
  
end

When the frame behavior determines that it is time to switch directions, it will send a changeDirection message to each and every sprite. Then, it is up to the sprite to change its own direction and drop down a few pixels. This is the handler that does that.

on changeDirection me
  -- move down
  y = sprite(me.spriteNum).locV
  y = y + pSpeed
  sprite(me.spriteNum).locV = y  
  
  -- reverse direction
  pDirection = -pDirection
  
end

The frame behavior is fairly simple, but critical to this whole process. If any invader hits the side of the screen, it sends a hitWall message to the frame behavior. The frame behavior records this event by setting the pInvadersHitWall property to TRUE. Then, at the start of the next frame, it will send out a changeDirection message to all of the sprites.

property pInvadersHitWall
on hitWall me
  pInvadersHitWall = TRUE
end
on enterFrame me
  -- see if an invader hit a wall
  if pInvadersHitWall then
    sendAllSprites(#changeDirection)
  end if
  
  -- reset wall hit flag for this frame
  pInvadersHitWall = FALSE
end
on exitFrame
  go to the frame
end

This is all the code necessary to make the invaders move back and forth and down. This invasion is on! Next week, we will come to the rescue by adding the player's ship and give it the power to shoot the bad guys down.

Download a sample D7 movie for the Mac or PC. This is a Director 7 movie.

More information about Gary Rosenzweig's new book, "Advanced Lingo for Games", can be found at http://clevermedia.com/resources/bookstore/book4.html. It can be purchased there, and is scheduled to be shipped to bookstores this week.

Gary Rosenzweig is the Chief Engineer, founder, and owner of CleverMedia, a game and multimedia development company in Denver, Colorado. He is the author of ten books on Macromedia Director and Flash, including his latest, Special Edition Using Director MX.

Copyright 1997-2017, Director Online. Article content copyright by respective authors.