This is a dev log about creating a game called Newtius in GameMaker Studio 2 (Indie edition). Starting with entry one might make this easier to follow.
After the diversions of entry 5, yesterday actually gave way to a large amount of productivity. Enough so that I ran out of time to to write about it.
Official newtius project page on itch.io is up
Note on this post: in the time it took me to finish writing this post I went from not having a lot of options for hosting the web version of the game to learning how to embed the game hosted on GitHub directly. I'll go into that in the next post. Now if only the HTML5 version could made into a PWA...
Up until yesterday I was working my way through the GMS2 tutorial create an arena shooter. In fact I would have the written version of the guide up in one window (it’s one long page) alongside the YouTube video of the guide, which is split into 8 parts.
And what I actually managed to do – through all 8 parts – is take what I learned form each video and figure out a way to apply it to Newtius.
The ArenaShooter game is actually quite a different game from what I had in mind for Newtius. For instance in ArenaShooter the ship is on a limited play field and rotates towards the mouse. The ship spins around and then fires continuously as long as the mouse button is held down. But Newtius is supposed to be the typical horizontal space shooter “shmup” so rotating the ship won’t be an option.
I put in things like the “spawner” object that creates infinite enemies, I implemented the hit points system of the enemy ships and I created the same enemy explosion sound event. I also created a sound event for firing from the ship.
Actually as luck would have it my favorite podcast played the perfect pew-pew sound effect recently. I downloaded the podcast MP3, imported it into Audacity, isolated the clip and exported said clip as an OGG file. Then created the event for firing from the ship. The OGG format seems more compatible with browser based version in my experience. A lot of asset packs seem include WAV files.
Well lets just skip slightly to the end here: I got up to the most possible working condition I could and put it on my itch.io page. I think I know how to embed it into WordPress now except I’ll probably replace the version I’m talking about with a later versions eventually making this whole progress report grossly out dated. The embed you see would be an “iframe” of what itch.io is actually hosting.
I tried to figure out how to make WordPress host the HTML 5 version but came up empty. So instead I’ll just point you to my GitHub repo and the EXE version of this primitive version of a thing in zip file called
newtius_pre-alpha-1 – 800×600 win exe.zip
Of course if you do want to play the game itself even if it isn’t this primitive form I’m describing in this post, you can do so on the page I setup for the game on itch.io.
Although what I could do is upload the current version to a different web game hosting site like NewGrounds and just not update it. At leas the primitive version would be accessible and preserved that way…Yes. I’ll probably do that.
Where was I? Oh.
I’ll think I’ll just go part-by-part and review what I added to Newtius from the tutorial.
In this section I already had a pretty good idea what I wanted to do as I had already gone through the Space Rocks tutorial which involves pushing space bar to fire a bullet. The AreaShooter used the mouse to both rotate the ship object and to fire the bullets so there wasn’t a lot of implement in this case. As with my variation of using the individual key press events instead of four lines in the step event, I just created a press event for the space bar.
This section did talk about creating a separate Bullets layer sandwiched in between the background and the Instance layers. And I’m sure it makes perfect sense but I still have no idea what it’s so important to have bullets in their own layer. I mean if they just get destroyed when colliding anyway.
// space bar pressed event
// using "var" for a variable means it's temporary and expires
// the below is just saying when the space is pressent create
// a bullet at the x/y coordinates of the ship object.
var newBullet = instance_create_layer(x + 0, y + 0, "BulletsLayer", obj_bullet);
// I think this is left over from the arenashooter spin around code
// where it mattered. it doesn't hurt anything so I kept it.
newBullet.direction = image_angle;
Next: the enemy section
This is where some interesting things start to happen.
It was pretty simple to just create the new enemy sprite and enemy object.
In the step event there’s this section
//this tests if the object_player exists
// and if so moves the enemy towards that
// player object's x and x at speed, spd
// (spd in the create event)
if ( instance_exists(obj_ship) ) {
move_towards_point(obj_ship.x, obj_ship.y, spd);
}
And if-exist for an object is convenient. It’s written in somethign of a short hand to get a quick true/false. And the game isn’t running if the ship stopped existing. So this is almost a while(true) sort of a loop. Almost.
Next is starting to setup the score system
// enemy object / step event
// when the hp gets to 0 destroy the enemy instance - hp defined in the create event
if ( hp <= 0 ) {
// which means do this thing to this other object. in this case the score object
with ( obj_score ) {
// add 5 to the score
thescore = thescore + 5;
}
// this just uses the death sound when the enemy is destroyed
// there's also this random pitch adjustment to give it a little variety
audio_sound_pitch(snd_death, random_range(0.8, 1.2) );
audio_play_sound(snd_death,0,false);
// when hp less then 0 destory the enemy object (boom)
instance_destroy();
}
Well the comments cover it pretty well: check if the hit points are less then zero. When hit points is less than 0, add 5 points to the total score. Then also play a “death” sound effect that accompanies the the destroy of the enemy object.
Being able to use the same sound but at a randomly altered pitch is actually something kind of clever. It allows for re-using of the same single sound effect while creating the illusion of multiple sounds. Seems like a good trick to keep the total size of game relatively small.
Enemy object / Create event: Here the HP and SPD variable are set to an arbitrary value, which I can adjust for balance as I like.
Enemy object / collide-with-ship event: consists entirely of
game_restart();
which I should probably change. To have an actual game over screen, display the score, encouragement to try again. Currently it just flips back to the title screen. Which I’ll get to.
Bullets
Bullet object / create event:
This is where the direction and speed – both reserved variables for use by GMS2 – are set.
Bullet object / outside room event:
This is just an instance destroy. The bullet is destroyed when it leaves visibility. it make sense, right?
Bullet object / collide with enemy object event:
I used the below code unmodified from the the arena shooter. As I speculate in the comments which I’ve included for some reason, the with other in this case can only refer to the other object related to this event which in this case is the enemy object.
// still trying to comprehend "with" and "other"
// well "other" in this context is probably the object the event defines
// which is collision and with the enemy object
// so "other" could be a true/false thing
// like as long as "other" returns true then subtract one from hitputs until it reaches 0
// at which point it returns false and goes to the destory
// that's the best explanation i can think of for the below
with (other) {
hp = hp - 1;
}
instance_destroy();
Or to summarize: when the bullet object collides with the enemy object: subtract one hit point. It’s also something of a shorthand for returning true that the enemy object in question still exists or my literally has a number hit points greater than that of zero.
Thus when the the hit points reach zero the last line executes, destroying the enemy object.
Not very exciting player object
I covered how to did the four movement keys in a prior post.
In the Create Event of the ship object I set the spd variable to an arbitrary number.
The only thing new in the key pressed – space event is playing the fire bullet sound. Which isn’t in the arena tutorial but wasn’t exactly difficult to paste in the line from the enemy death event.
var newBullet = instance_create_layer(x + 0, y + 0, "BulletsLayer", obj_bullet);
newBullet.direction = image_angle;
//audio_sound_pitch(snd_bullet, random_range(0.8, 1.2) );
audio_play_sound(snd_bullet,0,false);
In the area shooter there’s a seciont about tile sets, setting the size of the room versus how much the “camera” is showing the player and then how the “camera” can follow the player object as it moves around.
This is demonstrated by making the room twice the width, painting in the tile set pieces and having the the “viewport” just show what’s around the player object.
I didn’t do that for Newtius (yet) because I feel like I need to make a new tile set to match my game and it’s supposed to a continuously scrolling game (like Gradius) anyway.
I could use this method though: design out a whole level ahead of time, set a view port size then have the background scroll by and different barriers and enemies would spawn along the way. Actually I think that is the way games like Gradius were designed: the player stayed still and “map” scrolled underneath. So I’d have to design out a really long horizontal map.
Anyway that section of the written Arena shooter guide is really interesting. I don’t think the document has anchos so it’s hard to link directly to it. Just do a ctrl+f down to CAMERAS AND VIEWPOINTS and it’ll take you to the general area.
Adding in the score
I usually find the score sections frustrating because they always use the draw function. But this time it wasn’t terrible.
Score object / create event:
I just set the score variable, thescore, to 0 here.
I actually stopped to define a font here called fnt_score. I assume this important. Or will be later on.
Score object / draw event:
// objects use draw_self(); function if there are no draw events specifically defined
// things I learned:
// draw events happen once a frame like step events
// var is used for variables that disappear/don't exist at end of event
// these lines use the defined font and set the color of the font
draw_set_font(fnt_score);
draw_set_color(c_red);
// After some experimentation, figured out these set the score
// to the middle horizontally and and 25 pixels down from the top
ScorePosX = room_width / 2;
ScorePosY = 25;
draw_text( ScorePosX, ScorePosY, string(thescore) );
As the code implies, this sents the font face, sets the font color and establishes two variables for the position of where the score text will go.
Then a draw text function is used to put that score on the screen. The way this works seems clunky to me for some reason. Like GMS2 is just coming along with a crayon and manually drawing a string on the a physical monitor. I don’t know. Just seems like there’s a more elegant way to do that. Or I’m not looking at it the right way.
The award-winning title screen
Next is setting up the title screen. I just took the sample title screen from the walk through and changed it slightly so it had my blue ship instead of the arena shooter’s ship. Along side “my first game” and “press enter to start”.
I created a new “room”, rm_title, and opened that in the editor.

Then I found a different image that I could tile on the back ground and set the scroll speed to -1 to give a…scroll effect. Scrolling backgrounds that don’t make you do that work are so much easier.
This is actually all it takes to set that background tile to scroll right to left like that.
The negative one just indicates leftward.
That’s it. That’s all it takes.
For the fade in itself, I created the title object and associated it with my new title card sprite. And lastly, in the Instances layer, dragged my new title object into the rm_title room.
There was also something about making that title room the “top room” or the “highest priority. Well GMS2’s UI is slightly different than both the YouTube video and the written version but basically which ever room has a little house icon next to it in the “first” room.
Title object / create event:
// Title object / create event:
// make image inviisible at start of event
image_alpha = 0;
// set location
x = room_width / 2;
y = room_height / 2;
The image alpha is a transparency setting and a zero is all-the-way invisible.
The next two lines are just setting the x and y to the center of the room. Remember the previously “origin point”? Well setting x and y this way will center my title screen image, assuming that sprite has its origin point set to “middle center”. I also scaled it down a little bit.
Title object / Step event:
This is where the “fade in” effect happens.
// All this code is going to do is get the minimum value
// between the current image_alpha + 0.02 and 1
image_alpha = min(image_alpha + 0.007, 1);
The image alpha value is changed from the minimum value and incremental slightly until it gets to a fully visible 1. I adjusted these numbers until I got an effect I like more.
Title object / key up enter event:
This is just a room_goto_next(); statement. Although it’s pointed out in the walk through that room_goto(rm_game); works just as well.
So “when enter key released: go to the room labeled “game”.
Spawning enemies: The spawner and enemyspawn objects
First is the spawner object. This object doesn’t have a sprite associated with it and just sets the spawn rate and also sets an alarm variable:
Spawner object / create event:
// Spawner object "create" event
spawnrate = 120;
alarm[0] = spawnrate;
Spawner object / step event:
// this was altered from the arena shooter version
// my version is just along the right side 20 pixels in from the edge
// second instance is height y which is random (this will probably work
// I did it this way because my ship only faces one direction so there's no reason to
// spawn enemies behind it
// the enemies should still move towards the ship
// and this is spawning enemies on the enemy layer so I don't think it even matters which layer
// I drop the "object spawner" onto
instance_create_layer(room_width - 20, random(room_height), "EnemyLayer", obj_enemyspawn);
alarm[0] = spawnrate;
Basically (as I understand it) an alarm just counts down from an arbitrary value and executes the code when it reaches zero (or negative one as the case may be).
So if the variable spawnrate is 60 that’d be one enemy ever second (this was too much newtius so I set it to 120, much better).
Oh, and as implied I create an enemy layer for the enemies to spawn into.
Next there’s the enemy spawn object. This one is also associated with my enemy sprite
Enemy spawn object / create event:
// this sets the enemy spirte to a 10th of original size at
// object creation
image_xscale = 0.1;
image_yscale = 0.1;
Enemy spawn object / step event:
// this first line that xscale to itself + .02
// until it reaches 1
image_xscale = min( image_xscale + 0.02, 1 );
// and y scale just copies x scale's homework
image_yscale = image_xscale;
// is image scale at 100%? if so, it's enemy go time
// e.g. kill-the-player
if ( image_xscale == 1) {
instance_change(obj_enemy, true );
}
This obj_enemyspawn and obj_spawner objects both have to be dropped into the game room. In fact all the objects have to be in the game room in order for them to execute or do anything at all. In the case of the obj_enemyspawn and obj_spawner objects, they just shop and little tiny question marks. And at least one GMS2 video I came across mentioned putting these invisible objects in the upper left corner as a matter of unofficial convention but that it doesn’t really matter.
This seems right.
Wow this was an incredibly long post. I can’t imagine why I kept putting off finishing it. I hope it made some kind of sense. I don’t think future posts will be this long and detailed.
The good news though is that I can now host a playable web version of the on GitHub and use that to embed the game any place I want. I mean I can use itch.io for that as well. It just feels “better” some how if I have my game up on something I feel like I have a little more control over.
Actually I could probably make a post just about the git/GitHub workflow, rudimentary though it may be. It might help someone someday. Like me when I need a reference, for instance.
The latest version/progress of Newtius source can always be found at my GitHub repo: https://github.com/tildesarecool/newtius
One thought on “Dev Log Entry 6: Sounds and Collisoins”