DreemChest: Chain Reaction

About translation


Hello everybody. I decided to start translating the documentation for the DreemChest game engine, I don’t know if anyone did this before me, but I hope not.
Why did I decide to start with the translation of Chain Reaction? The answer is simple: this is the most interesting lesson with at the same time the practical part of the entire documentation.
Well, let's get started.

Chain reaction


This lesson will present an example of a simple game “Chain Reaction” (the name corresponds to the genre). The meaning of the game is that the player needs to destroy constantly appearing objects by clicking on them with the mouse, as quickly as possible.
The foundation

Launch the engine and create a new project. When it is launched, you will see a dialog box that asks you to create a new project or load an already created one. Enter the name of the project and click on the "Greate" button.

image
By standard, the editor has only one resolution of the game screen (320x480), but you can always add your own. Let's set our project a new resolution, for example 640x480, for this, open the pull-down menu (Well, honestly, I did not know how to translate correctly, correct if that), which is indicated in the image below in the main toolbar and select the "Edit" option.
image
Now you can see the dialog that just appeared. To add a new resolution, enter the width and height, in the first and second editing windows, and then click on the "Add" button. To close the dialog box, click on the “Close” button; to remove a permission, click on it, thereby selecting it and click on the “Remove” button.
image
Now that a new resolution has been added, you can select it in the pull-down menu, if you select a different resolution, the borders of the scene will be changed.
image
Adding Resources

The standard project contains only one htcehc with the name "root", which is the only game level (scene). Let's now add some sprites, which we will use in the future.
To import a resource, click RMB (Right-click) in the “Assest” panel and select “Import Assest” in the menu that just appears. We see a window appearing through which we will select and add our sprites. Let's add 2 sprites “Enemy.png” (“Enemy”) and “Bullet.png” (“Bullet”).
The “Assest” panel is located in the lower right corner, if you did not find it because it is not there, you can always add it via “View” -> “Assests”
image
The Assest panel allows you to create resources (script, shape, stage object, etc.), as well as import ready-made resources (Sprites, flash menus and sounds / music). To make a prototype of a future game, we need to register game logic, let's start by creating a script. RMB on the panel "Asssest" and in the menu that just appeared, select "Create" -> "Script".
image
Before writing a script, let's select the “bullet” and “enemy” resources. The image uploaded by us can be dragged onto our scene, but it cannot be called through a script if this script is not the main class of the object. So that we can create an object from a script, let's give the class of our object a unique name, for “bullet” it will be “bmpBullet”, and for “enemy” “bmpEnemy”, we can always change the name of the object class to another or write it for the first time by selecting object in the "Assest" panel, and then in the "Properties" panel, in the "Class" line, enter the name of the main class of the object.
The class of our resource can be called in any other resource, or attached to another object, but at the moment we are interested in working with scripts.
image
Let's start writing our script. The prototype of our script will contain 1 class and 8 methods.
Main - Method called when the game starts. Each main class must contain this method.
spawnEnemies - Creates a specific number of Enemy objects.
spawnEnemy - Creates a single "Enemy" object on a scene with an embedded sprite.
shoot - Creates 4 bullets at specific coordinates.
spawnBullet - Creates one “Bullet” object on a scene with an embedded sprite.
onUpdate - Updates objects (Coordinates, status, etc.).
updateBullet - Allows Bullet objects to move around the scene and checks for collisions with Enemy objects.
updateEnemy - Allows Enemy objects to move around the scene.

- Declare the Main class, derived from Graphics.
- To be able to make this the starting class, it must be a child
- of the Graphics class.
class "Main" (Graphics)

- Constants
Main.Enemies = 50
Main.EnemySpeed ​​= 100
Main.BulletSpeed ​​= 500
Main.EnemyTag = 1

- main
- Entry point which assigns message listeners and creates enemies
function Main: main ()

- Add handlers which react to clicks and updates
Stage.attachListener (TapEvent.Up, function (e) self: shoot (ex, ey) end)
Stage.attachListener (GenericEvent.Update, self)

- Rectangle which sets the window size
self.screen = Rect.new (0, 0, Stage.getWidth (), Stage.getHeight ())

- Set enemies loose
self: spawnEnemies (Main.Enemies)
end

- spawnEnemies
function Main: spawnEnemies (count)
for i = 1 , count do
self: spawnEnemy (Color.new (0.0, 1.0, 0.0, 1.0))
end
end

- spawnEnemy
function Main: spawnEnemy (color)
- Create an instance of the bmpEnemy class. It's the same identifier
- assigned to the enemy image in step 7.
local e = bmpEnemy.new ()

e.relX = math.random ()
e.relY = math.random ()
e.dir = Vec2.randDirection ()
e .color = color
e.speed = Main.EnemySpeed

- Each stage object can be given a tag. We use it to check for
- collisions between bullets and enemies.
e.tag = Main.EnemyTag

- Add the created object to the stage
self: attach (e)
end

- shoot
function Main: shoot (x, y)
local color = Color.new (1.0, 0.0, 0.0, 1.0)
self: spawnBullet (x, y, -1, 0, color)
self: spawnBullet (x, y, 1, 0, color)
self: spawnBullet (x, y, 0, 1, color)
self: spawnBullet (x, y, 0 , -1, color)
end

- spawnBullet
- The same thing happens here as in the spawnEnemy method
function Main: spawnBullet (x, y, dx, dy, color)
local bullet = bmpBullet.new ()
bullet.x = x
bullet.y = y
bullet.color = color
bullet.speed = Main.BulletSpeed
bullet.dir = Vec2.new (dx, dy)

self: attach (bullet)
end

- onUpdate
- Update message handler, called every frame.
function Main: onUpdate (e)
local i = 0
local n = self.totalChildren

- Scan the stage objects list and update them. We use objects'
- tag property in this method, to know which object to
- process: the enemy or bullet.
while i <n do
local child = self: getChild (i)

if child.tag == Main.EnemyTag then
self: updateEnemy (e.dt, child)
else
self: updateBullet (e.dt, child)
end

i = i + 1
end
end

- updateBullet
- Bullet updating method. We change its position every frame according
- to speed.
function Main: updateBullet (dt, bullet)

- We use the previously created Rect class object here, to
- determine if the bullet has flown off-screen or not.
if not self.screen: pointInside (bullet.x, bullet.y) then
- Each stage object has a release method, which removes it from the stage
- and labels it as unneeded. After a while, memory used by this object
- will be freed.
bullet: release ()
return
end

- Move the bullet
bullet.x = bullet.x + bullet.dir.x * bullet.speed * dt
bullet.y = bullet.y + bullet.dir.y * bullet.speed * dt

- Checking for collisions between a bullet and enemies is done like this:
- we sort objects relative to the bullet's location, with a radius equal to
- the bullet's size, and filter them using the tag property. The
- handler will therefore only be called for objects whose
- tag property is equal to Main.EnemyTag.
Stage.forEachInRadius (self, Main.EnemyTag, bullet.x, bullet.y, bullet.width,
function (object, distance)

- We found the appropriate object, which
- means a collision occurred. Shoot four
- more bullets.
Self: shoot (object.x, object.y)

- Delete the object and bullet
object: release ()
bullet: release ()
end)
end

- updateEnemy
- Enemy updating method. Simply move it on the screen. Wrap it around
- to the other side of the screen if it goes out of bounds.
function Main: updateEnemy (dt, enemy)
enemy.x = enemy.x + enemy.dir.x * enemy.speed * dt
enemy.y = enemy.y + enemy.dir.y * enemy.speed * dt

local w = Stage.getWidth ()
local h = Stage.getHeight ()

if enemy.x <0 then enemy.x = enemy.x + w
elseif enemy.x> w then enemy.x = enemy.x - w
end

if enemy.y <0 then enemy.y = enemy.y + h
elseif enemy.y> h then enemy.y = enemy.y - h
end
end


The script for the prototype of our game is ready. But why, when the game starts, nothing happens (To start the game you need to click the "Start" button on the main toolbar)? This is because our script is not selected as standard when the game starts. To fix this, you need to open the drop-down menu next to the "Start" button and select our script.
image
Testing and Export

The function of launching the project was made in order to save time that we spend on compilation in order to test what happened. To pause the game launched in the editor, click on the “Stop” button, which, when the game starts, replaces the “Start” button. If you edited the project and started it, but nothing has changed, then you forgot to save it (Ctrl + S), only after saving the changes will they become visible when the game starts.
image
Let's run our game.
image
To separate our project from the engine and export it to a specific platform, select the “Export” element (“File” -> “Export”) in the “File” drop-down menu. There you can configure many export options. (PS Exporting takes longer than a simple project launch and much longer).image

Also popular now: