Maze Raider - The aMAZEing code a game comp entry

Started by Derron, September 02, 2018, 13:45:09

Previous topic - Next topic

Derron

Kids in bed during noon so I had some hours to play.
Earlier this morning I already created some simple wall elements and painted some ground textures - pretty straight forward with texture painting in Blender and a digitizer pen. Most of the textures are most probably not visible in the scenes.


I tried out "godot" and most of the time I needed to look how to achieve certain effects (eg having a background image - used a "GUI control" for this, ahh yes). Also CPU utilization is rather heavy. 20% without lights, 50% of a core with just the lights visible in the video below.
The fire pillars are _very_ low poly and the fire particles itself are simple quads which get colorized gradiently. Zoom out and it looks a bit light fire. To create the "fire light"-effect I added a simple lamp to each fire pillar, set the fire particles to "not casting shadows" (else you would see rectangular-shadows floating around all over the surrounding tiles). Then I animated/keyframed the lights color over a period of 2 seconds (intensity + color). Each fire got a script attached which randomized position in the animation during start - so they all flicker a bit "differently".


So for now I need to say: godot has some similarities to Blender (which eases the whole animation-stuff) but some pretty hefty annoyancies (movement/scale/rotation shortcuts) also gdscript ... it's like Python ... is to get used to (as it is like Python - intentation dependend ;-)). Also filesize is pretty big (25mb for the runtime).
Let's see how that develops - or not.




Godot shot:


Blender shot (including a rather messy UV layout ;-) - I started all of them as simple place holders to get used to the digitizer pen)




Next steps (in some days) will be to try out how animations work: want to add some "traps" or spots at which mobs can spawn.
Most scripting is pretty "procedural" instead of the whole OOP I am used to. Also "auto completition" of the godot editor is ... non-existant if you instantiate objects ("var bla = tileWall.instance()") so if you do not know the commands you always need to google the documentations.


bye
Ron

Xerra

That looks really good, Derron. Are you going to create a worklog thread or just waiting until you come up with a game name first?
M2 Pro Mac mini - 16GB 512 SSD
ACER Nitro 5 15.6" Gaming Laptop - Intel® Core™ i7, RTX 3050, 1 TB SSD
Vic 20 - 3.5k 1mhz 6502

Latest game - https://xerra.itch.io/Gridrunner
Blog: http://xerra.co.uk
Itch.IO: https://xerra.itch.io/

Steve Elliott

#2
Yep some good progress Derron - keep going!

Quote
so I _just need to make it addictive *shrug*

I find that a very weird statement *all* games should be addictive.  You disagree?  Why are you shrugging?  A simple or complex game - it doesn't matter!  All games should be addictive, or they're not good games!

A complex game that is no fun is far worse than a simple game that keeps you coming back for 'just one more play'.
Win11 64Gb 12th Gen Intel i9 12900K 3.2Ghz Nvidia RTX 3070Ti 8Gb
Win11 16Gb 12th Gen Intel i5 12450H 2Ghz Nvidia RTX 2050 8Gb
Win11  Pro 8Gb Celeron Intel UHD Graphics 600
Win10/Linux Mint 16Gb 4th Gen Intel i5 4570 3.2GHz, Nvidia GeForce GTX 1050 2Gb
macOS 32Gb Apple M2Max
pi5 8Gb
Spectrum Next 2Mb

Derron

Of course games should be addictive - but sometimes I think certain game mechanics "aren't". Especially if you play things during development you might loose some "addiction" as you eg. know how to handle enemies the right way. So you do not need to figure out how stuff works to reach perfect highscores. To avoid this you need "AI" which surprises you here and there. But a tough AI is more than just "rather complex". It is a pretty big task.


@ Qube
Feel free to moderate and put the posts about my "wip" into a new thread (maybe, call it "Competition entry: Maze Raider" and I could adjust the title later on). That would keep the thread a bit cleaner.


bye
Ron

Qube

Mac Studio M1 Max ( 10 core CPU - 24 core GPU ), 32GB LPDDR5, 512GB SSD,
Beelink SER7 Mini Gaming PC, Ryzen 7 7840HS 8-Core 16-Thread 5.1GHz Processor, 32G DDR5 RAM 1T PCIe 4.0 SSD
MSI MEG 342C 34" QD-OLED Monitor

Until the next time.

Derron

Thanks ;-)


Added some spike-traps this morning to try out how to handle animations. I thought of animating them in Blender but at the end placed and animated stuff in Godot then. So each spike of a trap got its own animation time line in a single "animation" (Spikes.Activate, Spikes.Deactivate).
Godot is really "string"-centered. So stuff is referenced by strings (get_node("bla/bla.tscn"), animationPlayer.queue("Spikes.Deactivate")). While this adds a lot of convenience it does not feel clever performance-wise. Think whole stuff is "scripted language-"-esque for now (no clue what happens to c# code or so as I am just trying out the gd script side for now).

Stopped my quick "place trap instead of ground tile" try as somehow the object has switched y and z axis (while it is not rotated!) and when placing the items on the 3d environment they here and there had some "y axis offset" (which should be an z-axis) so in other words it looked as if the objects were "sunken or raised" a slight bit - and this depenend on the x/y positions. Really odd and annoying moments: you always have to google for reasons and solutions and this without knowing what the right termina for the problem is.

What I like is the integrated animation stuff ... so you see how it "looks like". What I dislike there is, that when doing your "scenes" (each object is a scene and scenes can contain scenes ... so like "Prefabs" at the end) your light/environment is wrong. So all my tiles look blueish, dull instead of getting presented in a neutral color. For my fire pillar I needed to judge by the gradient I used for the fire - not by what was rendered in the scene preview (there I could only verify the animation/particle movement). When appending this scene to the level scene (which contained an world environment / lights) it looked like it was supposed to look.
I surely just need to setup some default stuff somewhere else.


I've read about collision stuff in Godot and many examples use this for free movement of your entities. I think it is better for the cpu utilization to have a grid based collision check (tile occupied? then you cannot go there) and only use a "rigid body" check when it comes to "mob vs player" meetings ;-)



The game is currently planned to be a simple "collect some stuff, activate some switches, avoid monsters/traps" game. Collect the needed stuff and solve the simple riddles (whatever I will come up) and the door/hidden-ladder/... to the next level will open/enable passing through.

Monster models I create are surely useable for my "Trick or Sweets" game (environmental props). Code hmm, for now not really reusable in my other projects.


Might post some screens when on my dev computer / at home again and the kids in bed.

bye
Ron

Qube

I like the early look of the first video. It's not far off the angle I have planned for my game ( should I get the actual bloomin chance to code anything ).

The subtle light effects are cool and I look forward to seeing development shots ;D
Mac Studio M1 Max ( 10 core CPU - 24 core GPU ), 32GB LPDDR5, 512GB SSD,
Beelink SER7 Mini Gaming PC, Ryzen 7 7840HS 8-Core 16-Thread 5.1GHz Processor, 32G DDR5 RAM 1T PCIe 4.0 SSD
MSI MEG 342C 34" QD-OLED Monitor

Until the next time.

therevills

Looking good, Derron!

Quote from: Derron on September 03, 2018, 11:39:44
Godot is really "string"-centered. So stuff is referenced by strings (get_node("bla/bla.tscn"), animationPlayer.queue("Spikes.Deactivate")).

I've been learning Godot too, slowly getting the hang of it. I'm learning GScript and found out the other day you can use $item instead of get_node("item"):

So:
get_node("Label").text = "HELLO!"
can be:
$Label.text = "Hello!"

Once most of the C# stuff is done/fixed I'll be moving over to that instead of GScript.

Derron

Good to know that there is somebody out here who might be able to help if I run into problems ;-)


bye
Ron

therevills

Haha! I'm just learning and doing 2D :)

Godot 3.1 looks good with optional typing which should help the code completion issues in the IDE.

MikeHart

Looking good Derron. I will utilize the same toolchain.

Derron

I compiled godot "3.1-dev" meanwhile - resulted in a 130mb file, compiled with some modules disabled (not used formats...) and it failed after some hours of "linking" + "compiling". the Theora-decoder seems to need "opus" support and failed in some deep-for-loops then. Have read about runtimes truncated to 7mb uncompressed and 2mb in the final apk file. Of course they miss the 3d part then, but for 2D (therevills?) this might be an interesting thing to try out. Same for the windows/linux/... binaries.

The "autocompletition" was still not corrected - and as I have read about the issue, their excuse is that it is a dynamically typed language and they never can assure what kind of type is really passed.
I understand this for things like

func myfunc(someparam):
someparam.???


but I do not get how they do not understand:

func myfunc():
var tileGround = load("res://Tiles/Tile_Ground.tscn")
tileGround.???

I mean, the "tileGround" thing can change (from what it extends) but in the moment of typing it _could_ get resolved.


Only working solution is to have something like

func myfunc():
var tileGround = load("res://Tiles/Tile_Ground.tscn")
if tileGround is (or extends in godot 2.x) Node2D:
tileGround. #works

This is absolutely awful for someone who tries to learn the language + the multiple types and their functionality.





Game progress:
I had about 45 minutes yesterday (so 50% more than Qube ;-)) and wrote some script stuff to handle AStar for pathffinding. In Godot the 2D tilemap and the 3D gridmap (far too limited for an "3.x" - even if they implemented 3D later on) have some support for pathfinding. You could also do some navpath3d thing or so but this needs support in your 3d models (similar to collision meshes). AStar is useful for simple grid maps (grid occupied or not). Should be way better performing.
So I wrote some grid hashmap (similar like the "TMap" in BlitzMax)  containing all valid grid cells needed by the AStar class. All cells are then passed to the AStar class and node connections are established (grid cell x has leftside nothing, rightside another walkable grid cell, ...). Means afterwards the algorithm can calculate paths.
If something on the grid changes (wall breaks down, door opens, ...) the grid hashmap is refreshed and the AStar class gets a new list of datapoints added.

That way the pathfinding is no longer strictly limited to the actual tilemap - which might contain the ground tiles or wall definitions but has (for now) now clue about potential obstacles.
But I already thought of replacing it with some kind of 2D array and then add different layers for "obstacles" or "collectibles". This is the right spot at which I lack a lot of knowledge. Tilebased stuff was new to me in the last competition (the "creature corp" entry). Of course I now try to do things better (or at least different) which does not mean I do it properly. Arghh ;-)

I already know that I will spend hours of time developing stuff which at the end is doing pretty odd stuff to make it work in a fully-bugged way needing more and more hacks to keep it doing what it is suspected to do.


How would you guys manage the tilemap + collision stuff (think of many tiles being objects able to get "asked" if they are walkable/collectible or not - like doors, traps, coins, ..) ?


bye
Ron

Matty

Managing the tilemap query you had:

The way I do it is like this (javascript - so different language but same approach)

object 'battlemap' which is an array of objects
each element of battlemap (index = x + y * maxgridx) has the following properties:
.tile = 0 or 1, 1 = floor tile, 0 = wall tile
.creature = index to creature array - indicates if a creature is in the cell or not
.terminal (for my game I have computer terminals...I have a 'terminal' property which is true false if there is a terminal in the cell)

pathfinding:
I don't bother worry about creatures but only tile positions.....if I were pedantic I'd include the .creature index (-1 for empty) in the pathfinding as just another obstacle (1 creature per cell).

That's my method...the method i've always used for almost 15 years.....

Derron

#13
So in other words:
- you store gridcell-objects
- assign mobs/collectible-items to these cells (think to save some lookups)

Dunno how much it affects performance if you need to lookup cols*rows arrays compared of a "occupied grids"-list. Think for small levels it should be neglectable and a good way to keep code a bit easier.

So I would have this:
- array/list of grid-objects
- grid-object contains: (static) walkable, cell position (col, row), position (x,y,z) for rendering, list of "contained" items (creatures, collectables,...)
- array/list of creatures/collectables (again but to save traversal over all grids just to update/handle these units)
- when updating creatures/collectables and moving over/in/out-of grid cells, the gridcells get informed and update "contained items list" + update their walkable-state (so you could have moveable blocking-stones...)

Of course above requires multiple lists/arrays to be kept in sync but it allows a faster access when it comes to collision/interaction-checks. grid objects only need to scan a handful of items in their "containing list". If creatures want to know about the tiles they walk on - how do you tackle this (except having all definitions in one file - means A knows about B and B about A). Looks a bit "dirty" to me.

Or am I missing something?


Thanks for exposing your tilemap-approach.


bye
Ron

Matty

Hi Derron...the easiest way to explain is with an example. ..on my phone so can't share links easily but if you look in my code (js link in my thread) and look at the references to 'battlemap' and its elements it should explain better than my words.