December 2016 Game Dev: 2D PCG Shooter

Honestly was not even a consideration. I mentioned it as more of an FYI if I fail to report in or otherwise experience an unexpected slow down.

All in all this project is probbbably about a tier 4 prioriy after Religious, Family and Work obligations.

We already have weapons as a sort of base-level power up system, so I agree with pushing NPCs are a higher priority. I will start work on that immediately.

This will nescessitate a change in how I am handling AI, so that the AI system is more contextual and choice based rather than dumbly honing in on the player.
This is something I have been thinking about mechanically for a little while and fits with the current development requirements so I will take a brief look at this while I work on the NPCs and their mechanics.

NPC rescuing should for the moment just give a substancial point boost, we can look at tieing them to a more robust rewards system later Insha Allah if there is time.

Once basic NPCs are in place I might take a look at the very simple powerups such as health-packs and speed boosts.

I have ideas for more intresting enemy types/behaviors and powerups / special weapons/abilities, but I will keep them all firmly on the backburner until instructed otherwise.

I am hoping that with these base requirements tied up, the final week can be a blitz of experimental features and balancing.

Salaam all,

I just pushed V1 of the NPC rescue mechanic.

NPCs appear as blue triangles, similar to the players white.
On spawning they will very slowly wander around the screen, until a player approaches them.
Once near the NPC will start to follow the player. If lead to the center of the screen safely, they disappear giving a heap of bonus points.

AI has been adapted to allow for multiple targets.
I was experimenting with AI decision making and giving them some sort of Idle wandering state until a target entered their agro range, but this has been shelved for the moment in exchange for a simple range based selection. (Attack nearest target).

I was attempting to create a 2D grid representing regions of the game map that would be weighted against their desireability. Having a player or NPC in a region increases the enemies desire to go there while having other enemies or bullets in that region decreases desireability.

This worked to a point, but was not refined enough to look presentable. enemies trended towards better locations while not specifically locked onto a target. However if 1 nearby region was not significantly superior to the others, they would get stuck in a local-maxima and awkwardly vibrating on the spot.

I might persue this again if there is time, but for now Always agro against the nearest target works well enough.

The player gun has been swapped back to the pistol as the start weapon.
The Railgun pickup has not yet been created, so for now it is unobtainable unless specified as the starting weapon.

Beware of machinegun, shotgun and rocket fire as they are equally effective on NPCs as they are monsters.

Less ethical players may find it easier to gain points by herding NPCs as bait for enemies rather than leading them to safety.

I got some art from @roketfiq. These are all sort of a work in progress.

The Dajjal:

The new background (he thought the player in a spaceship):

The new crater (an asteroid):

I could add a significant amount of drift to player movements (Like Asteroids).

IE:

on keypress: player.mx += 0.1
on update: player.x += player.mx
           player.mx -= 0.001

Or more traditional asteroids movement:

on keypress w/s: player.thrust = +/- 0.1
player.mx+= player.thrust * sin(theta)
player.my+= player.thrust * cost(theta)
on keypress a/d: player.theta +/-= 0.1*pi/180
on update: player.mx *= 0.5

^^ I just tried adding this. It is actually pretty fun.

And an Asteroid enemy type.
AI only traveles along itsā€™ initial vector, on death spawns copies of itself @ half scale.
Despawns safely as it leaves the screen.

No reason we couldnā€™t go that way.

Has anyone here ever played ā€˜The World Ends with Youā€™ on NDS?
The enemies in that game had a very strong Street-art art style and were effectively Jin.
Rokets art style does have a street-art feel to it. I like it

@BloodMoney seems determined not to be a part of this thread. He should be the Final Word on this as a game designer. Since heā€™s absent, and youā€™ve already said itā€™s fun, Iā€™ll try it and probably agree, and we can ship it. Could you enclose it in a if (config.get('...')) block so we can turn it off in one step later if we want?

I like @roketfiqā€™s art style too. While I really liked the pixel art, thereā€™s a different ā€¦ feel to this art style.

One issue I have is: how are you in prison if youā€™re in a spaceship? We should probably change the name.

config(ā€˜InSpace!ā€™)

1 Like

Har har.

Fine, it doesnā€™t matter. I would choose something more descriptive like physics_motion or something.

In all seriousness though I will probbably set the options as ā€œAbsoluteā€ and ā€œRelativeā€ controls.

@ashes987 did you get a chance to pull my NPC code I pushed last night?

Any comments or suggestions to refine it further?

I didnā€™t get a chance, no. I recalled yesterday from my MITx that professional studios spend something like 30% of their budget on tutorial. It really is that important. So Iā€™m freaking out and trying to get it done.

The config.json name doesnā€™t matter. Thatā€™s internal. Weā€™ll ship a single, self-contained executable to the end-user, so they wonā€™t even see it.

I had some brain waves today about the intro and plot. Hereā€™s the plan I have now:

  • The intro (Dajjal) mentions chasing you to the ends of the galaxy, ā€œMuslim meat!ā€
  • Then the intro (player) mentions: hyper-drive is damaged, here they come!
  • Rescuable NPCs are escape pods from other Muslims who were hunted down
  • Rescuing NPCs shows a ā€œcrew: Xā€ counter. And this explains the passive bonuses very nicely IMO.
  • Weā€™re procedural. Weā€™ll generate a random ā€œspace backgroundā€ by choosing one of four starscapes, five planets, and two nebulae.

That will make it look unique each game, and the theme flows completely from weapons to rescue.

Do you approve, co-game-designer @severok?

Sorry, I didnā€™t have time to try the NPCs yet. InshaAllah soon.

Iā€™ll leave it to you to decide how much investment the tutorial is worth.

I like the idea of rescuing NPCs contributing to passive bonuses, like they are contributing to your ships overall crew count.

Not sure if you have played ā€˜Space Pirates And Zombiesā€™ before, but they have a similar mechanic where you can collect crew as a resource by picking up escape pods from downed ships or stations and the more crew you have on board the more effective your ship is.

We could do something like a Hyper-drive charge counter. The player collects so many crew members and the Hyper-drive starts charging, if you take a hit it drops back a bit. Crew will boost the ships speed/weapon fire rate and repair the hull over time.

As the level progresses, the enemies start spawning faster and faster as they all ready do, so the player is trying to accumulate crew and get the system up and running as fast as they can before they become overwhelmed.

Once the Hyper-drive is charged, the ship jumps to the next location. New level starts with additional weapons and enemy types added to the spawn lists.

Edit:
How does this sound for a storyline.

Following your whole, Trapped by Dajjal story line:
The player is captain of a military ship (For reasons) and is trapped by Dajjal in a pocket dimension where it is set upon by waves of his minions.

The ship has an experimental drive allowing it to slip between dimensions, but the Dajjal has damaged it in his trap.

The crew of the ship must try to repair their disabled ship before it is torn apart, rescuing as many survivors as they can.

Escaping from their first prison, the crew of the find that they are a long way from home and have to jump from pocket-dimension to pocket-dimension until they can once again return home. Along the way, they encounter more and more of Dajjals minions lurking in the depths of space and reality. (New jump = new level, later levels = more enemy types).

@Art team, if you can make us some sprites, I can code us some new enemies.

Salaam Team,

Checking in, I have tuned up the reletive control scheme.
This can be selected by selecting ā€œcontrol_styleā€: ā€œrelativeā€ in config.json.
changing this to ā€œabsoluteā€ (Or anything else really) will reset the control scheme to our previous controls.

The reletive control scheme handles much like the classic Astroid controls.
W/S keys act as forwards/backwards, A/D acts as left/right. The ship accelerates and drifts

Tonight Insha Allah I will work on passive enhancements for the player ship.
My current plan is that instead of additional pickups, I would like to incorperate the NPC rescue mechanic.
I already have the NPC AI responding to player distance, holding position when close to the player. I am thinking that if we can use this as a docking proceedure between the player and the NPC, where if you can hold distance then the NPC is added to a player crew count.

I would like to buff the player ship based on the number of crew. Gaining crew when rescuing NPCs and losing crew when taking damage.

Crew: 5+ : Health regen (Upto 5 lives)
Crew: 8+ : Engine Speed +
Crew: 11+ : Reload spead +
etcā€¦

In addition to this, when the player has 5/5 lives (Ship fully repaired), the ship jump drive starts charging, counting down until level completion.

From here on, we should be able to trigger a game restart, selecting a new background and new spawn lists unlocking tougher enemies and better weapons as the game progresses.

Edit:
We now have a crew mechanic that passively upgrades the ship based on how many crew members you currently have.

This needs some balancing as reaching 30 crew made me horribly over-powered.

Edit: Signing out.

Change log: Ship crew update.

  • NPCs are now collectable to add to players ā€˜Crew countā€™
  • Crew count contributes to passive ship upgrades including
    • Life generation (Ship repair)
    • Ship speed increase
    • Weapons fire-rate increase
    • Weapons reload-rate increase
  • Crew count probability (1-3 chance) decrease on damage.
  • Reaching 5 lives (Max / Ship fully repaired) initiates a ā€œJump-driveā€ counter charging
    • Todo: Enable stage advancement when drive charging reaches 100%
  • Taking damage disables drive-charging until ship is fully repaired again.
  • Corrected ā€œRelativeā€ control scheme
    • Reduced weapon-recoil

Todo/Bugs:

  • Multiple NPCs appear to be spawning at once on top of eachother.
    • Collecting 1 NPC should increase crew by 1. currently increases by 2||3
  • Currently trialing player screen wrap similar to asteroids.
    • Possibly remove.

So far I have been able to get the Jump-drive upto around 20% charged before getting overwhelmed by enemies. Which means I currently have approximately 1/5 of the skill required to reach stage 2.

I havenā€™t tried this yet. InshaAllah I will tonight (~12 hours from now). My gut feeling is:

  • We need to make crew bonuses for each crew member. The player wonā€™t last more than 2-3 or so before dying.
  • The hyper-drive was an ā€œunknownā€ that I was leaving for future game design discussions. I intended that charging it => win the game.

Thereā€™s a game on Kongregate (not sure the name now) that starts off when your car breaks down. You have to repair it (press/hold R next to it) while shooting dark enemies (unknown shadows), which get progressively stronger over time. You can upgrade your gun, health, build turrets, etc. to help.

That game ends when you finally repair to 100%; you jump in and drive off, leaving the darklings behind.

I rather enjoyed that game, and I thought we could use a similar mechanic here, albeit that the user doesnā€™t actively recharge/repair the hyper-drive.

BTW, if you make any more game mechanic changes, please preserve the old behaviour and/or keep a config switch to toggle the new behaviour. That way, we can run it by other people and get a second opinion (or I myself can catch up and see all our options) as need be.

I just pushed my work for the night.

If you want to keep it as a single stage then have new enemy types add in over time, that is fine.
So far it seems difficult enough to charge the engines or a single stage, let alone expecting the player to do it over 10 or so stages.

The current upgrade list is as follows:

    if self.crew > 3:self.repair = 0.001                        #Emergency repairs
    if self.crew > 5:self.speed = self.stock_speed * 1.2        #Engineering crew
    if self.crew > 8:self.attackrate = 1.2                      #Tactics crew
    if self.crew > 11:self.reloadrate = 1.2                     #Gunner crew
    if self.crew > 15:self.repair = 0.003                       #Repair crew
    if self.crew > 18:self.speed = self.stock_speed * 1.5       #Engines tuning
    if self.crew > 20:self.attackrate = 1.5                     #Weapons tuning 
    if self.crew > 24:self.reloadrate = 1.5                     #Ammo management.
    if self.crew > 28:self.speed = self.stock_speed *1.8        #Advanced Engine tuning
    if self.crew > 30:self.reloadrate = 2                       #Advanced Ammo Management

Where Attackrate and reloadrate are modifiers to the stock gun stats, scaling each weapon picked up approriately.
Speed is the player movement speed and repair is life gained /frame (limited at 5 lives, at which point the jumpdrive starts charging)

This gives roughly

  • 1 life/ 33 seconds with a crew of 3
  • 1 life/ 11 seconds with a crew of 15

With the current rate of NPC spawns and the bug that picks up 2-3 crew / rescue. I can reach 25-30 crew without too much issue.
This will need to be nerfed before release.

I added a config option for selecting the control scheme between the old style and current.
I can add in others later to toggle NPCs and ship bonuses.

I just pushed dynamic backgrounds. Itā€™s semi-ugly, but functional. Sorry, Iā€™m not as uber an artist as you @severok (mashaAllah tabarakallah).

Sorry, I pushed to your branch by mistake. Please pull/merge.

Three randomly generated ā€œworldsā€:

It looks like it is time to start pushing for more efficient code or atleast multi-threading.

This just crawled to a pause, with my CPU usage pushing a little over 25%.
Looks like we are maxining out a single core, in what I am guessing is primarily our brute force collision detection.

Time for Quad-Tree detection?

Edit:
In the spawning code, I have game running on a budget system.

  • An enemy type is selected at random.
    • Each enemy type has an associated spawn cost.
  • Every frame, player recives a spawn income adding to a hidden score, when that score exceeds the cost of the next enemy spawn, the enemy is spawned.
    • This balances both the number of enemys on screen, but also allows weaker enemies to spawn faster.
  • On each enemy destruction, the spawn income is increased causing enemies to spawn faster as the game progresses.

This section of code starts with a loop: While Spawn_budget <= Spawn_cost:
Meaning that enemies & NPCs can continually spawn in a single frame provided the spawning budget allows for it.

I added in an extra check to count the number of spawns / frame, printing out the result, what I found was that at the start of the game everything spawned singularly, 1, 1, 1, 1 but as the game progressed, somewhere around 400 points I was spawning something like 10 - 20 enemies in a single frame and growing.

At the moment I am considering that perhaps NPCs were spawning and colliding with enemies off screen causing the kill count to increase uncontrollably resulting in a major slow-down/freeze.

replacing this loop with a simple conditional so that only spawn can occur / frame, the game became Significantly easier with far fewer enemies on the screen at any one time. It seems strange that the difference is so drastic as I should still be spawning 30 enemies / second with this code if my spawn_income is so high, so I must investigate further.

I think youā€™re following a red-herring. I would use the roketfiq cheat for unlimited health, and quickly reach the point where I have ~100 enemies on screen. MASSIVE slow-down.

Honestly, my opinion? We shouldnā€™t allow monsters to collide with monsters. This grows exponentially with the number of monsters (itā€™s O(n^2)), which means going from eg. 4 => 5 monsters increases the checks from 16 => 25.

There are other easy work-arounds (eg. check if enemy A collides with B, then donā€™t check again that B collides with A) but honestlyā€¦ just having player-monster, bullet-monster collision checks should solve this.

If it doesnā€™t, I would do maybe a 4x3 quad tree. Quad trees are a bunch of extra work, and weā€™re down to the last 2-3 days, so Iā€™d rather skip this if we can.

On the bright side, it looks like weā€™re basically done! Iā€™m the bottleneck now on the story integration :frowning: can you focus on bug-fixes please? I seem to be finding an awful lot of them now.

They dont.

That is why I catagorise object types into seperate lists and why NPCs are loaded into the player list

Players and NPCs collide with bullets and monsters
Monsters collide with bullets.

This is how I have always done it.

This is from obj,py responsible for selecting which objects to check for collision detection.
It has been there since the original rectangular collision

    def collision(self): 
    for player in Player_list: 
        if player == Player_list[0]: 
            for pickup in Pickup_list: 
                player.pickup(pickup) 
        for bullet in Bullet_list: 
            player.Circle_collision(bullet) 
        for enemy in Enemy_list: 
            player.Circle_collision(enemy) 
    for enemy in Enemy_list: 
        for bullet in Bullet_list: 
            if enemy.Circle_collision(bullet):  
                sound.enemy_hit.play

There is also a simple check at the start of the actual detection function to check the ownership of bullets before processing. If the bullet is being checked against the object that fired it, the function is returned without processing further. This was done to prevent players from shooting themselves, but also helps skip unneeded processing.

I feel that I should be identifying any section of code involving multiplicaiton and trignometry and applying checks to see if they are really required.

I know in microcontrolers, I am always looking for alternatives to multiplying. using LUT to pre-calc common values (Such as Sin, cos and regular exponents) and bitshifting for doubling and halving.

If I limit movement directions to 16, 32 or even 64 directions, I can remove a heap of processing times by reading pre-calculated dx and dy values using the angle as an index.

From this point on, I will move off features unless instructed otherwise and I will focus on bug-hunting and efficiency.

IMO, a major source of slowdown will be in the AI target selection. Every frame they are currently selecting targets by evaluating distance to player and every npc then chasing the closest.
When there are multiple NPCs on screen this gets very expensive.

I will set a cool down once the ai target has been selected so that target and heading is updated every few frames rather than every frame

I am taking my wife shopping today, so please update the bug list on git and I will Insha Allah start hunting tonight

The ā€œde-factoā€ way to fix performance bugs in software (not micro-controllers, for contrast) is to:

  • Find a case that reproduces the bug reliably
  • Run a profiler against the code in this case
  • Discover the problem. It could be memory, CPU, GPU, anything.
  • Try to fix the problem
  • Re-run the workflow and verify if the problem is there (if so, GOTO 4)

Guessing (trig, etc.) may work but again, the only way to know for sure is to re-run that case and see if it slows down or not.

For the AI bottleneck, which is IMO legit, I would suggest just calculate the target at spawn time and stick with it. Thereā€™s no need to ever revisit it.

Iā€™ll see if I can profile or something. BTW, thereā€™s an excellent spawn cheat which you can modify to flood the game.


Checking in. Please pick some bugs to work on and add your name in brackets so I know youā€™re working on it / pegged it. The plan is to finish by the 27th (including QA), which is enough time to tweak art and get this thing out the door by the 30th, inshaAllah.

If weā€™re done bugs, please proceed to power-ups. Please put it in a separate branch (eg. powerups) so that we can axe it if we donā€™t finish in time.

I have the intro + tutorial in my head. Iā€™ll try to get that done over the next hour or so, inshaAllah. Thatā€™s the last required feature.


I hardly made any progress on the tutorial. If this project fails, and the failure is because of that, I will be fully to blame for it.

On the bright side, I finally figured out why my splash screen times assume 60FPS. It turns out there was a bug in main.py where we scheduled frame_callback twice: once in a schedule call and once in a schedule_interval call. Removing the former, fixed it.

The game felt slow as molasses, so I updated a bunch of speeds/healths to make it feel normal. Feel free to pull and poke it if itā€™s out of whack.


Done for now. Thereā€™s infrastructure for a tutorial window, you can click or press space to get rid of it.

Checking in.

It really is the eleventh hour. BloodMoney and roketfiq are nowhere to be found these last four days. InshaAllah we will prevail none-the-less.

Key question: do we ship this as-is (mostly generic 2D PCG shooter with mostly generic weapons/theme) or spend the next month experimenting and really making it shine? Perhaps we should ask the broader MG community? (Perhaps not if weā€™re booked next month with other commitments?)


Checking out. Made progress on the tutorial (added steps to GitHub ā€“ LOTS of work to do). Fixed a couple of crashes and stuff. Melee seems broken, sadly (I couldnā€™t figure it out). Please merge as usual and see what you think of the tutorial.

Melee is a work in progress. I am rekejiggering tr mechanic to make it more thematically appropriate.

Rather than a melee attack it will be a point shield to protect the ship across a very small area controlled by the mouse.

Left click for attack, right click for defence.

Makes more sense than a ship swinging a sword and would help to complement ranged combat instead of competing with it.

My understanding of this project was 3 projects over 3 months. The first being more or less as generic a project as we could do to see how we work as a team and a point of reference that we can compare later projects against to see how we have developed.

I am leaning towards shipping the project on the original planned date as polished as we can get it, though I will accept if you want to persue it further.

Given the nature of this project is to see what we can produce in a month, it sounds out of scope to extend it further so if we continue work on this project, then we should atleast plan some significant changes to implement so that at the end of month 2 it is essentially an entirely new project rather than just the continuation of a project you otherwise felt fell short.

At this point the current project is greatly in need of more art assets since we are now 2 days from shipping and still using the place holder sprites I threw together in 5 minutes.

For the duration of the current commitments, I think we should stay with the current tech stack of Python with Pyglet since we now have some experience with it. Though I would like to have a go at some other genres along the way (Point-and-click adventure, physics puzzler, RPG, etc).

We should pick our direction based on our team makeup, IE an adventure game will need a strong commitment from the art team while a physics puzzler is more mechanically based.

I am good to go January which ever way we want to go, though I will have to request a brief delay on month #3 moving into febuary as I am planning to travel for 2 weeks.