Monday, September 24, 2018

GPS is not dead. Long live GPS!

GPS is going to have to take a few weeks off. I just started a new job and it's....hard.

Once I get into the groove at work, I'll get back into GPS a least a couple of days a week.

Some news though:

  • So far, GPS has three different levels:
    • All caps because the in game font doesn't have lower case :-)
    • SKOOL with boss MR. CORTMANDER
      • still needs some enemy tweaking, but the level can be completed
      • Also, MR CORTMANDER has been colorized.
    • TANKTANKZOMBIE with boss TANKTANKSUPERTANK?
    • POLYGON WARS with boss POLYGON OF HORROR
  • Difficulty Select at beginning of game:
    • MOM MODE - even my mom can play it. True, I made her.
    • EASY - Pretty hard to die, pretty hard to get high scores
    • NORMAL - RNG can occasionally be ruthless, but should be a balanced play
    • BULLETHECK - it hates you. Starts of normal, things escalate quickly
  • Irregularly shaped rooms
    • Initial rooms were all rectangles. 
    • Took some doing, but now they're not. 
    • Some of them are easier, some of them are actually kind of annoying depending on RNG
  • Some tileset rework has been done. More needs to be done, but it's getting there.
  • Still no mouse support
  • Fully playable with keyboard or controller
    • need to refactor input code to account for controllers other than mine and mouse.


Tuesday, September 11, 2018

Gamemaker paths "orient" (rotate) around ZERO not their first point.

So, I was making some paths for my enemies to follow, specifically, a path that sort of looks like a bouncing ball. I said soft of. It's Graph Paper Shooter, not a ball bouncing simulation.



Since it was so simple, I just started drawing on the path editor.
I was not careful to make sure my first point was zero. That led to some unexpected behavior.

The idea was that these particular enemies would leave the spawner and orient their path such that it pointed in the general direction of the player. For this to work, I needed to set the variable "path_orientation" after I told the object to start following the path.

Here's the thing: when setting path_orientation in GMS2, the path will rotate around the 0,0 point (x=0, y=0) as defined when the path is created in the editor. It does not rotate or orient around the first point of the path, as you might expect. The documentation for path_orientation does not mention this. The docs for path_rotate (an actual function) mention this, but path_rotate rotates the original path object, not the path you're using.

So, just a heads up. When you use path_orientation and your paths are going completely the wrong direction, check that your path starts at the origin.

Sunday, August 26, 2018

Changelog for August 26, 2018

It's been a heck of a week, family health issues have kept my busy pretty much up until the weekend.

The weekend has, however, been productive:
  • Complex enemy pathing has been implemented
    • This took the bulk of the time, deserves its own blog post
    • Enemies will now go around complex obstacles and room shapes to get at the player
  • Irregularly shaped rooms are now an option and have been implemented
    • More work than it sounds like :-)
  • Completely rewrote player movement code 
    • no more "bouncing" off walls
    • if moving at an angle the player will slide across the wall in the non-blocking direction
  • Player and enemy bullets now asplode when hitting walls
  • Enemies no longer fire if they're not facing in your general direction
    • will still fire at walls though. 
    • They are stupid
  • New hidden wall type to keep the player from cheesing bosses (by sneaking behind them)
    • Can fire through these
  • Added "Robbietron" tileset and enemies
    • Uncolored boss is drawn:

  •  Added four (so far) irregularly shaped rooms, including what is probably the most annoying one ever, the "five minute hallway". 
    • takes about 400 health ticks to traverse the entire width of the room. 
  • Added configurable backgrounds based on dimension (space, desert, tanktankzombie, etc)

Wednesday, August 15, 2018

Changelog for August 15, 2018

  • Still stuck on Polygon of Horror fight design, so doing other things...
  • Got started on the "tanktankzombie" boss fight - "TANK TANK....SUPERTANK"

    • I may add a "?" to the end of the title. First I have to draw it (and all the other punctuation, which is on the todo list)
    • brought super tank artwork into GMS2
    • created title screen
    • tank shoots giant bullets at you. whoopdedoo. 
      • it's a start

  • Generalized boss room startup code
    • setting common variables
    • drawing the boss health bar
  • Made minor changes to health management script so that bullets values aren't static
  • Minor adjustments to the boss_dead screen - still not happy with it
    • Now it just says "NICE" gps-style with all the dead monsters splatted on top of "NICE";
  • Minor adjustments to the Mr. Cortmander boss fight - you can't cheese him by climbing under his desk anymore.
  • Colorized all of the text with screens using GPS-style text
  • interstitial rooms no longer tick off your health or show the score UI
  • Completed the Options screen:
    • music volume
    • sfx volume
    • full-screen mode (yes/no)
  • Decided on a new Dimension: 
    • THE OUTSIDE
    • filled with crap you find outside (you know: bitey critters)
    • Boss: THE SUN.
      • It should never be 102 degrees in Helena MT.
      • I wanna kill the sun.
  • Not playing World of Warcraft (everyone else in the house is) 

Monday, August 13, 2018

From paper to living enemy

I am not a very good artist. My line control is unstable. My circles are rarely round. And while I can use graph paper to make geometric shapes that are based on moving from square to square, I have difficulty making free-form drawings that are in any way symmetrical.

So, I fudge it. For something like the spider queen, I drew one half of the queen until I was happy with it, and mirrored it.
First I drew her on lined paper, then scanned it in.
Next step is to use paint.net to turn her into a monster.
The four images above are:
  • The original scan
  • the original scan minus the paper lines
  • Then I mirrored the original image 
  • Then I colored it
Then I "animated" the "test", by making a bunch of frames where they were in different positions, and the result is thus:
  
For the "Polygon of Horror", the boss is protected by shield generators that look like this:
They spin. And you might notice that it's more or less perfectly symmetrical. 

  • Drew just the one arm as two separate pieces
  • Scanned it in
  • pulled the paper lines and artifacts out of the image
  • Then I assembled the two pieces as separate layers
  • Then copy/pasted the arm 3 times adding 90-degree rotation each time (for a total of 8 layers)
  • Then I started coloring it in.
  • The smaller center piece is just a scaled down copy of the the outer piece
  • The center circles are little bit of cheating,
  • I didn't actually draw those by hand, but rather decided once it was in the game that it needed a little "ejector" from which nastiness (for the player) will spawn.

Saturday, August 11, 2018

Collisions

So, I'm working on the boss fight for the "Polygon of Horror" where the boss and the shield generators have shields up part of the time. The player ship needs to bounce off of them. Since this is a twin stick shooter and not a platformer, collision detection and behavior need not be complex. In fact, it needs to be simple.
And it has been up to now. Simple, but tedious. On wall collisions, the player object was literally checking to see which wall object it was hitting and then acting accordingly. This involved putting "left" walls on the left of the room, "bottom" wall on the bottom of the room and so on.

It was not, how you say in America, a general solution.

Well, for a round object like a shield, this is obviously not going to work, so I had to come up with something else. And I did:
//get the center of the object I just collided with
px =other.x
py =other.y

//get the difference in position between my center and that of the object
tx = x - px;
ty = y - py;
//get the sign of that difference
sx = sign(tx);
sy = sign(ty);
//get the X to Y ratio of the line between the two points
//in absolute terms
ar = abs(tx/ty);
at = abs(ty/tx);

//assign a new location "15" ish pixels from the collision in the opposite direction
x += sx * (min(15, 15 * ar))
y += sy * (min(15, 15 * at));
//YAY, no trigenometry

When the player collides with an object now, I run the above and it bounces 15 or so (will tweak it later) pixels in the opposite direction. I could probably get it down to like 4 lines of code, but this is actually readable.


 Next, I created a single collidable wall object (instead of four) and surrounded the room with it:
 Those grey blocks (which are invisible at run time) are all identical, and the code to deal which each is exactly the same. Th exact same code is used on the shields in the boss level:
This also means that I can finally get around to having the player ship actually collide with the enemy spawners (to their detriment)



Friday, August 10, 2018

What I'm working on right now....(8/10/2018)

Normally, I'd post a change log for today's date, but nothing that I'm working on is actually done yet.

Right now, I'm working on the boss fight design for the Polygon of Horror boss fight.
This has required learning about the realities of dealing with paths in GMS2. Maybe I'll go into that another time. Now that I've got it down, there will be lots of bullet hells :-) And...more than likely, a much needed design on the "Mr. Cortmander" boss fight.


Since I want the shield generators (in the corners) to also spawn enemies, I had to generalize the enemy spawn code  and turn it into a function. Previously, it was only run by the enemy spawner, so it's not a case of "had the code in a bunch of places", but rather a case of "I totally do not want this in two places". There's some complicated crap going on in there. So, now things other than "spawners" can spawn enemies.

Also, while I was at it, I decided that I wanted the player ship to bounce off the shields around the generators and the boss. So I spent about an hour working out a generalized solution to bouncing the ship off of stuff. Such as the walls. Right now, the ship checks to see if the ship has a hit a "left wall", and if so, moves to the right. If it hits the "right wall", it moves left.

The new code figures out where to bounce the ship to based on the difference in the location between the center of the ship and the center of the object it just hit. This gives me the information I need to figure out which direction the ship needs to bounce. On on the one hand it means I have to put more (hidden) "wall objects" on the borders of the rooms. On the other hand, it means that they can all just be the same kind of object and only one collision check, which is now generalized, needs to be run.

Have also been working on new art for powerups, new monsters, and the elements of the boss fight shown above. Showing off the new monsters will have to wait until I put together some web friendly image strips.

And finally, the inter-dimensional interstitial has been redesigned. Now it just randomly splats all the critters you've killed on that level all over the screen. Kind of like how the "Next Dimension" screen does it - but, to be clear - one picture for every single enemy killed.



Wednesday, August 8, 2018

Change Notes for August 8, 2018





  • Interstitials
    • Next Up:
      • Shows you what's going to happen on the next dimension
      • Floor and wall art change to match what's up coming
      • random enemies from the upcoming level are thrown at the screen.
      • May decide to animate them in the future. May not.
    • End of Dimension
      • Shows you a visual representation of all of the critters you've killed
      • Not sure I like it.
      • If I do, then on the sound design phase, I'll change it so they show up "one at a time" which a stomping noise. Or maybe once stomp for each type of enemy.
        • yeah, that seems more likely, otherwise, we'll be here all day.
  • Fix a few bugs:
    • The dimension picker was all messed up
      • I was trying to be too clever when I first wrote it
        • If the code you write is at the limits of your cleverness, then you are, by definition, too stupid to debug it.
        • I was.
      • Had to rewrite it from scratch
        • Actually works now
      • At game start, it shuffles the list of available dimensions.
      • You'll go through that list until you've seen them each once.
      • Then it reshuffles.
      • So, the last of one complete run and the first of the next could be the same, otherwise, you won't see duplicates.
    • Found another "script_execute" bug or three.
      • Had my functions calls formatted wrong which resulted in some odd behavior.
      • Will do a dev-blog post on this as it's an interesting GMS2 specific behavior
    • My point-defense upgrade for the missile rig was setting the score rather than adding to it (= rather than +=)

Monday, August 6, 2018

Change Notes for Auguest 6, 2018


Today was a busy one: Added the Unlocks menu, and more importantly, made it do things.


  • New Unlocks menu:
    • Unlocks now having meaning
    • Ships
      • Select from unlocked ships 
      • Put the Original Prototype back in as playable
    • Guns
      • Select from unlocked guns
        • If you've chosen a ships which doesn't have built in guns.
    • Grid Schemes
      • Select from unlocked graph paper schemes
      • Each scheme has a light and dark background 
      • Added a new grid scheme (red)
    • Drones
      • Select from various drone shapes and colors 
      • Added bunches of new drone skins
    • Added flavor text for all of the above
    • Functionally, it does exactly what it should, I may tweak the design a bit
    • Your selections are saved as your default so you only have to pick them once.
  • Found a bug in the health management system which sets off bombs? 
    • What the actual fuck? I don't even know how this is happening.
    • Will fix it tomorrow
  • Found a bug in the missile explosion code 
    •  Missiles were destroying spawners regardless of HP and no points were awarded.
    • Fixed.
  •  Added keyboard support for most functions 
    • Main Menu
    • Unlocks Menu
    • High Score Entry
    • Actually playing
      • Left Stick=WASD
      • Right Stick (Firing) = Up/Down/Left/Right
      • DPAD (Menu Nav) = U/D/L/R
      • (A) = Enter
      • RB (Bomb) = Space
      • ESC = give up (but enter initials if you got a high score)
    • Mouse is coming. Eventually.

Sunday, August 5, 2018

Change Notes for Auguest 5, 2018

  • Finally got around to saving an INI file.
  • Currently stores 
    • music and SFX volumes (which you can't actually set)
    • High Scores - this is the big one
      • Top 5 high score
      • What you were driving when your game ended
        • Both the ship type and gun upgrade level
        • Ships like the Polygon Warrior only get on pictures
        • Ship/gun combos such as UFO/Missile get a two pics
          • One for the UFO 
          • One for the gun showing the upgrade level of the gun
  •  The game over screen now shows your final score
    • If your final score is a high score, you get to enter your initials, old school arcade style
  • Added "Unlocks" and "Credits" to the main menu
  • The Unlocks screen will be where you choose:
    • Your ship and weapon (if appropriate)
    • Ship colors
    • Drone colors
    • Graph Paper color schemes
    • Possibly other things as they occur to me

health powerups (re: dammit I love this engine)

I was looking at the todo list, looking for some low hanging fruit, as it's already been kind of a long day....so I decided to do two things: add health powerups and increase the pickup radius for powerups, in general.

Time from start to finish: less than 5 minutes.

And that included time making a bouncy red "H" sprite to act as a placeholder for the graphic. (All of the powerup graphics will be remade once I figure out how I want to do them.)

Basically, it went like this:  First I created a health powerup object. It doesn't actually do anything except wander around and bounce, the code for which is already part of the generic powerup code. Then, I opened up the player object, created a new collision event which checked to see if the player collided with  a health powerup. If it was, add the value I put in the variable "health_powerup_health" to the players health, and destroyed the powerup. Then I added the health powerup to the drop table for dead enemies. The value of the variable "health_powerup_health" will, of course, be determined by the difficulty level. Once I implement difficulty levels.

While I was at it I increased the size of the collision mask for all of the powerups, which effectively increases their pickup radius. I may need to do that again. Play testing will tell for sure.

Five minutes. And this wasn't even with code that will need to be refactored later because it sucked.
I'll be refactoring the powerup drop mechanics later anyway, but only as part of a design pass - there are certain things I haven't decided on yet: do I limit the number of powerups that can drop? Do I go ahead and leave that be since you sometimes get really unlucky and nothing drops? Right now, an enemy could, in fact, drop one of everything as each powerup is check separately.

I'll probably set a standard drop rate of like 50%, and then make it so that each dead enemy only drops one powerup 99% of the time. For the last one percent, they'll drop something else too. The game relies very heavily on drops to ramp up the action. I've already lowered the overall drop rate, and I'm not happy with the results. My initial thought was "too many powerups on the screen", so I lowered it. Now, I sometimes struggle to get through the first minute of the game, especially when the RNG hates me.

Unless I'm playing the UFO with the missile rig, which is seriously just easy mode right now. That thing really needs to be nerfed.

It took me longer to write this post.

Saturday, August 4, 2018

Change Notes for August 4, 2018

  • Reworked how health is lost in all the ways
    • Tweaked the health tick per frame value (it was way out of hand)
      • Is now .5 + (.01 * total room count * dimension count per frame)
      • That's 30 points per second plus a little bit as you progress
      • will probably get tweaked in next balance pass
    • when your bomb gets set off by an enemy (or enemy bullet):
      •  you now lose health based on the enemy score
      • bullets no longer count 
        • more than 15 or so on the screen would insta-kill you 
        • but they do get destroyed
    • health is properly applied when you set off a bomb on purpose
    • moved all of the health loss code into a single function to ease future changes:
      • balance passes
      • adding difficulty settings
    • health gain and loss is based on enemy score value rather than enemy health
    • updated score values on all enemies to make it possible to kill things fast enough to live
  • Light blue graph paper grid not getting picked up by video capture software
    • made grey and white grid
      • gets picked up by video capture software
    • still need to apply said grid as default everywhere
    • at least I know what the problem was
  • Decided on a new feature: the ability to select your graph paper themes
    • Will start with two defaults 
      • For "light" levels:
        • dark grey on white
        • original blue on white
      • For "dark" levels:
        • original blue on black (which does get captured)
        • light grey on black
    • Others will be available as unlocks
      • will probably be eye-bleedingly obnoxious

Dammit, I love GameMaker Studio

So, the other day, I was working on a "point-defense" system for the player missile rig. This is a feature where after some powerups, the player ship will automatically fire at incoming projectiles.

Projectiles only. It's not supposed to be an offensive weapon. The missile ship fires slow and wasting missiles to get bullets out of the way is kind of a waste. So, point defense.

Well, as of yet, I had not had to find out which objects of a certain type are near the player. Most of the combat logic is based purely on collisions which have object data built in. So, I did a quick search to see how you find nearby objects in GameMaker Studio.

instance_nearest()

Well, shit. That was easy. Five minutes later, my point defense system was done.

Well, done-ish. It still needs some balancing, but it does exactly what it's supposed to do.

This happens pretty much every time I wonder "how do I do this thing?".

Dammit, I love this engine.

Friday, August 3, 2018

Change notes for August 3, 2018


  • New powerups:
    • Drone powerup - give you temporary help
    • Has same bullet power and fire rate as you
    • Lasts 30 Seconds, getting more powerups resets timer
  • Replace unusable powerups with "score" powerup
    • Right now if your speed or fire-rate are maxed, you get points instead
    • But, the graphic doesn't change, it should 
  • Rewrote the powerup spawn code
    • now, when fire-rate or movement speed are maxed, it generates a new powerup
    • some potential for infinite recursion if I'm not careful
  • Rebalanced health mechanic:
    • max health is set to 1000 * dimension count 
    • Current health degredation is .01 per frame (60fps, do the math)
    • Either the max health or the health tick will be based on difficulty settings
    • health powerups (currently worth 100) can raise it past max
    • killing monsters raises health based their score value (up to max)
      • monsters deal (monster score * dimension count) damage
      • bullets deal (10 * dimension count) damage
      • Everything in boss rooms does double damage
    • bombs getting set off by enemies deal damage for every enemy killed
      • This seems "ok"
      • They also deal damage for every bullet they hit
        • That will pretty much insta-kill you if high fire rate enemies are present
    • Might change bombs to do a flat percentage of health, 
      • or ignore bullets
      • capping might also work
        • but requires a rewrite of what is currently very simple code
  • Bombs that you set off on purpose, of course, increase your health (but not past the max)
  • Fixed UI scaling
    • not sure if this was due to an upgrade in GMS (patch yesterday) or what
    • UI scale on full screen flat out failed.
    • The fix, happily, made UI scaling easier.
  • Added "Dimension <dimension name>: dimension count" to UI
    • So it looks like "DIMENSION THE BOX: 1"
    • It looks better in the in game font which is all caps. 
  • Added new death effect to polygon wars enemies
  • The missile rig doesn't seem OP any more. 
    • Apparently due to other balance changes mentioned above

Why GameMaker Studio

After some digging around and experimenting, I decided that I would write a game in GameMaker Studio 2. Why GMS2? Simple: it does precisely what I need.

The process started with "I think I'm going to write a game".

I've already done some work in Unity3d, and frankly, that's more engine than I need.

I've taken a look at Unreal Engine, and if I was going to do a graphically intensive 3D game, open world or shooter or something, Unreal looks like the right tool.Also, if I had a team. A team would be good. I just have me.

I figured that I don't want my first foray into this to be something overly complex. So I checked out GMS. Three of my favorite games (Siralim, Siralim 2, and Siralim 3) are all written in it, so I figured it had to be worth something.

Turns out, it's awesome.

Why not write my own engine?

So many reasons. I've been futzing with computers most of my life. Starting with basic on the VIC-20, then assembly on the C64. These days it's Python, Bash and Hadoop stuff. Point is, I know an exclusive-or from a hole in the ground. So, I can code my way out of a paper bag. But what that really means is that I don't want to write any code that I don't have to.

Writing your own game engine is a job unto itself. Aaannnndd... writing your own engine kind of requires that you know what you're going to do. I didn't. It requires that you know what features you need. I didn't. And it takes freaking forever to write all that low level code just to get a freakin sprite on the screen.

I do not have that kind of time.

GameMaker Studio handles all the low level crap for you....and a fair amount of the high level crap, to boot.

At it's simplest: you give it a graphic, attach the graphic to an object, make a "room", put your object  in that room, and then tell GMS what the thing should do. Does it move when I push a key? What happens to it if it runs into a wall or another object in the room? All these things are basic but would take forever to build from scratch. In GMS it is literally a matter of minutes.

I should make a tutorial. But I probably won't. At least, not until Graph Paper Shooter is done. Besides, they have plenty already.

And here's the super important part: GMS handles all the stuff that has to happen in the background for a game to run. During every frame, stuff has to happen. GMS keeps track of the frames, the order of operations, and you just tell it what happens and when. Which, if you're designing a game is really all you care about.

What happens. When.

In this case: left stick move, right stick shoot.

Thursday, August 2, 2018

Graph Paper Shooter: the evolution of a little shooter

Graph Paper Shooter started development a mere month ago.

First thing, design the player. I started with this little thing. Keep in mind this was literally drawn by me, on graph paper. And yeah, it's sad:
Once I got tired of looking at that thing, I scanned in this little "ufo thing". Both the ufo thing and the walker above were designed to have different rigs (their various gun types) applied to them:












The guns look like this (for now...):
 In order, those are:
  • The original gun (drawn with the original walker)
  • Lazer Gun level one and two (that's Lazer with a Z, you can't see real lasers)
  • The sawblade gun (I have yet the record the "poink" sound it will make on firing.
  • Missile launcher levels one through three
Next, I drew what was originally going to be just a gun, but after some modifications decided to make it into it's own ship, the "space fighter".

And, finally, the most recent ship, is the "polygon warrior". This ship will be unlockable by beating the Geometry Wars inspired Polygon Wars level. It has four upgrade levels, the first of which is shown here:
 
As you can see, this was actually drawn on graph paper.
Most of the artwork is either drawn on graph paper or notebook paper. I usually start the designs in my notebook (graph paper is expensive, yo) and then move to graph paper for the final rendition. However some, like the space fighter above, turn out just the way I want them in the notebook so I scan than instead, and we end up with lines in the artwork instead of little graph paper squares.




Once they're scanned in, I colorize them using either "Paint.Net", the Gimp (for functions paint.net doesn't have), or in the GameMaker Studio sprite editor.

 Below are all four (yep, a whole four) frames of the space fighter. Right now, it's the only player ship that has individual frames, which in this case are simply the change in color on it's butt to simulate it's little space engine. The ufo thingy, above, rotates. The speed of it's rotation is based on your current firepower. Its rotation is independent of the gun rotation, which points in the direction of fire. The polygon warrior and the space fighter rotate to match the direction of fire.