Introduction: Battle City Remake on GameGo With Makecode Arcade
GameGo is a Microsoft Makecode compatible retro gaming portable console developed by TinkerGen STEM education. It is based on STM32F401RET6 ARM Cortex M4 chip and made for STEM educators or just people who like having fun creating retro video games. You can follow this tutorial and try the game in Makecode Arcade simulator and then run it on GameGo.
In this article we're going to try our hand on recreating a classic Battle City tank shooter game, originally produced and published in 1985 by Namco for Nintendo Entertainment System (NES). In the original game the player controls a tank and shoot projectiles to destroy enemy tanks. The enemy tanks attempt to destroy the player's base, as well as the player's tank itself. We'll make some modification to the game play to better accommodate block programming practices with GameGo, but our remake will still retain a lot of similarity to the original game. Let's begin!
Step 1: Our Alter-ego - Yellow Tank
Open Makecode Arcade at https://arcade.makecode.com/ and click on new project. We'll begin my making our alter-ego the yellow tank. Choose Set mySprite to sprite of kind player block and draw a yellow tank facing upwards as our starting sprite, put that block inside of on start block. Add move mySprite with buttons block. Now we have a tank that we can move with buttons in simulation! Great, but it is always facing the same direction, even when we move down or sideways...
To correct that, let's add four more blocks, one for each direction button.Create a new variable, called direction - we will save the direction of movement of our tank in it, 100 will correspond to down, -100 will correspond to up, 200 for right and -200 for left. Why these numbers? You'll see later, when we add the projectiles that our tank will fire. The logic within each four of these blocks is very simple - we check if new direction(from button press) is the same as direction before. If it is, we basically don't do any changes. If it isn't we change the tank's sprite and in case with downward and left direction we flip the sprite's image to avoid drawing additional sprites. Finally let's assign the starting value of direction to -100 (tank upwards), since this is how our tank starts the game. Try moving the yellow tank now, the sprite will change according to direction of the movement now! Excellent, now let's add bullets.
We'll fire bullets with set projectile to projectile (draw small silver square for that sprite) from mySprite with vx vy velocities. Inside of on button A pressed block, we need to check for absolute value of direction to see if yellow tank is facing up/down of left/right. We then proceed to fire the projectile with the velocity of direction variable - that's why we had -100/100/-200/200 for direction values.
Now we have yellow tank that can fire projectiles and move. If yellow simulated tanks could have feeling it would surely feel lonely in this blank void without enemies and things to do. So, for the next step let's add enemies for it to pass the time.
Step 2: Bring Out the Enemies
We'll start this step by creating a bunch of new variables: two arrays (one for holding enemy sprites and another one for holding enemy directions), spawn time variable for storing the time period between spawns, enemy count for storing maximum number of enemies at the same time. We'll also add two projectiles(projectile and enemy projectile) firing in on start block - that will help us to avoid an error later.
Next we create on game update every ... ms block, insert spawn_time variable there.The logic inside of the block is simple - if the total number of enemies at the battlefield is less than maximum allowed number of enemies, add an enemy to enemy_sprite_list and add 200 (going right) direction for that enemy.
Next, in the on created sprite of kind Enemy block we add some graphical effects, place it on a random empty tile and call pick_direction function for this sprite. In on sprite of kind Enemy hits wall, we call the same function, pick_direction.
What is in that function? Here is where things start to get a little bit complicated, so hold on. There's 50 percent chance of enemy tank going up and 50 percent of it going down - we change the sprite accordingly. The only trick here is that we also need to change the value corresponding to that particular enemy tank in enemy_directions_list to it's new direction, so we'd have it fire bullets in the right direction. For that we find the index of enemy sprite in enemy_sprite_list and change that item's value in enemy_directions list.
Finally, let's add shots firing. We add another on game update every 500 ms block and put a for item in enemy_sprite_list. With 30% chance an enemy sprite will fire enemy projectile in it's movement direction.
If we launch the game in simulation now, we can see our yellow tank and enemy tanks appearing in the same point and going into empty space. We can shoot and they can shoot our yellow tank, but nothing would happen. It feels so devoid of meaning still :) Let's add the decorations and game mechanics as the last step.
Step 3: 42 of the Game
We're going to start this step by adding life and score from Info tab and setting life to 10 and score to zero. Then we add block set tile map to ... . Draw the file map to look something like you see in the screenshot above. Don't forget to add the walls!
Let's add on sprite of kind Projectile overlaps otherSprite of kind Player - this is when enemy's bullets hit our yellow tank. We need to make sure these projectiles are enemy's bullets and not our own, so we'll add that if condition within block and if it evaluates as True, then we subtract one from life count. Similar to it, in another block on sprite of kind Projectile overlaps otherSprite of kind Enemy we make sure that projectile is a projectile from yellow tank and if this condition evaluates as True, we destroy otherSprite(the enemy tank), remove it from the list of enemy_sprite_list and add one to score.
The last thing is victory and defeat conditions - for victory, we'll check if score is higher or equals 10 in forever block. If it is, then we show the victory screen. And in on life zero block we show the Game Over screen.
Now try it out in the simulation to see if the game is running as expected. Then upload it to GameGo and enjoy smashing enemy tanks!
Step 4: Endless Game and Improvements
In our GitHub repository you can download two files for Makecode arcade - one is exactly the same you would get if you follow this instructable and the other one is upgraded version, which has randomly generated level progression. It has 10 levels, each one is randomly generated with increased number of enemies in each successive level.
And of course, there is even more things you or your students can add to the game on top of that! There's better music, breakable walls, different victory conditions and so on!
If you do make an improved version of the game, share it in the comments below! For more information on GameGo and other hardware for makers and STEM educators, visit our website, https://tinkergen.com/ and subscribe to our blog.
TinkerGen has started a Kickstarter campaign for MARK(Make A Robot Kit), a robot kit for teaching coding, robotics, AI!