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.
Copyright 1997-2024, Director Online. Article content copyright by respective authors.