Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

Advanced search

1408566 Posts in 68942 Topics- by 62843 Members - Latest Member: Melon771A

September 21, 2023, 08:35:20 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityDevLogsDinosaur-Ghost Rampage (Tentative Title)
Pages: [1]
Author Topic: Dinosaur-Ghost Rampage (Tentative Title)  (Read 2016 times)
Level 0

View Profile WWW
« on: January 22, 2016, 07:55:51 AM »

Hey! I just found these Dev Logs! Neat idea... I'll try to post here regularly.

So, I just wrapped up my last game (http://blastingagent.com) and released it earlier in the month, and I've already started on the next one.
Awhile ago, I tried challenging myself with making a full game a month. One of the games that came out of it was Dinosaur-Ghost Rampage (http://dinoghost.tims-world.com/). It had a simple design: run around and destroy stuff for as long as you can.

The Original

Whenever I go to events and show off my games to people, this one has always been the 'favorite' for some reason. People will sit down and play for way longer than I expect them to, and seem to have a blast. So, it was only natural that I would want to turn this into a bigger, fuller, better game.

First things First, I'm using HaxeFlixel (http://haxeflixel.com), which is the BEST. I am also not an artist, so, a lot of things are going to be programmer/placeholder art until later on.

Thinking about this project, I wanted to try something new that I hadn't done before. So, I decided to try doing an Isometric style, instead of the top-down style of the original. This turned out to be a bigger headache than I thought.

HaxeFlixel doesn't have any built-in isometric stuff, yet. Someone had started working on something, but they never got very far, so, I was left to figure out my own logic. It took about 3 days to get it figured out. Basically, I ended up having 2 versions of everything - I have a regular, 2D Tilemap, and a bunch of regular, square, 2D objects that handle movement and collisions, and then I link a special IsoObject to each of those 2D objects which get placed on the screen based on their 2D counterparts. This way, I don't have to do any complicated Isometric movement logic or collision, I just let everything play out in 2D space as per usual, and then adjust their projections into Iso-space accordingly. It also allows me to stick all 2D stuff into it's own camera and turn it into a minimap!

2D Mapping

Once I had this figured out, it was pretty easy to get the player's movements working, and a simple enemy-tank which pathfinds around the map looking for the player.

The eternal struggle: Dinosaur-ghost vs Tank

The next fun bit I decided to mess around with is more of a style-thing. If you notice in the original game, there's something missing: no cars and no people running around in panic. I decided to fix that.

I drew up a super-simple dude and put him in the game. Whenever a building is destroyed, some random number of dudes pop out and run around until you step on them or they get run over by a tank. Hey - life is hard for pixel-folk. Now, I didn't want to just have one dude and populate the city with clones, and I didn't want to sit there and draw 100 different dudes, so, I looked into something that I had heard of: paletteMap. Once I figured out exactly how to use it, it turned out to be simpler, faster, and better than I had hoped. I took my dude-sprite, chopped it up into smaller bits, saved the bits in grayscale, and texture-packed the bits. In code, whenever I want to create a dude, I take the bits, pick a random hue for each bit, and then apply paletteMap using that color, and stamp them all together into a new image. It works great.

I used a similar approach for the cars, as well.

Cars and People!

Next up was a fun part. Up until now, I had just made a simple csv for my maps to read from. Again, I didn't want to sit there making 100 maps for my game... I'm too lazy for that. So, I built some functions to generate maps for me. In the game, I have 7 'sizes' of buildings. Each size = how many hits it takes to destroy (and how much energy you get from it when destroyed). For the sake of being easy to see, I made them all color-coded, so the 'weakest' building is purple, while the 'strongest' is red.

I defined a few parameters for my maps - dials that I want to adjust as the game progressses to be able to make harder and harder levels. I came up with: Size (how big the map is), Density (how close the roads are to each other), Level (roughly how strong the buildings are in the map - low level is more purple buildings, etc), and Connections (how many roads exit the city and act as spawn points for enemies).

First, I make a blank canvas using Size, then, I add some perlinNoise to make a random mess of stuff on the canvas.

Next, I blur my image to make it a little smoother between building sizes.

Then, based on my Level, I darken or lighten the image some amount - this ensures that I have more buildings of the right size for my Level.

Next, I use threshold to apply the color for each of my building-strengths to the map, based on the darkness of the pixels.

Finally, I carve roads and connections onto the map based on Density and Connections.

The life cycle of a map

And that's is! I pass the final image over to the map building logic and it creates the actual tilemap based on it.

Map made of parameters: Size = 50, Density = 3, Level = 8, Connections = 6

...and that's just about where I am right now! I've added a few other minor things, like the player's 'energy' bar at the bottom of the screen and the 'Destruct-O-Meter' on the right. I'm still playing around with different win conditions and things, and working out how the game is going to play out. I think the next thing I want to work on is a world-map, and the start/end for each level... we'll see how it turns out.

Thanks for reading this, I hope you enjoyed it!

Level 0

View Profile WWW
« Reply #1 on: February 04, 2016, 08:45:38 AM »

Hey everyone. It's been a little while. I've been busy with work and the Global Game Jam (http://mission-imp.tims-world.com) and everything.

I don't have a huge update, but I wanted to show off the map logic that I came up with.

Basically, I knew that I wanted my maps to work something like the Mario 3 maps. A series of nodes that you can navigate between (once they've opened up).

First, I defined my levels themselves, using JSON.
  {"id":0, "type":1, "style":0, "size":16, "density":1, "level":1, "connections":1, "enemies":[0], "spawnRate":10, "destructGoal":500 },
  {"id":1, "type":1, "style":0, "size":16, "density":1, "level":1, "connections":1, "enemies":[0], "spawnRate":10, "destructGoal":600 },
  {"id":2, "type":1, "style":0, "size":18, "density":1, "level":1, "connections":1, "enemies":[0], "spawnRate":9, "destructGoal":700 },
  {"id":3, "type":1, "style":0, "size":18, "density":1, "level":1, "connections":2, "enemies":[0], "spawnRate":8, "destructGoal":800 },
  {"id":4, "type":1, "style":0, "size":20, "density":1, "level":2, "connections":2, "enemies":[0], "spawnRate":7, "destructGoal":900 }

This is the first 5 levels in the game, with all of the details that need to be passed to the map creator.
id = the level's id number
type = the kind of map it is - the only type I have right now is '1' which is 'destruction' where the goal is to fill up your destruction meter to 'win' that level.
style = is not used yet, but is planned to set the tiles used for this map, so we can have a variety of different looking cities.
size = how big the city is
density = how close the roads are packed together in the city
level = defines the height of the buildings - higher level means more taller buildings
connections = how many roads reach the edges of the city - which is also the spawn points for enemies
enemies = defines which enemies will spawn in this level (I only have tanks ["0"] right now)
spawnRate = how fast enemies spawn in seconds
destructGoal = how much the player has to destroy to beat the level

This file is read in when the game starts, and the level definitions get stuck in an array, so that if I want `level[0]` it gives me the properties of the first level, etc.

Next, I started setting up my map screen. This was much trickier than I expected. I knew that I wanted to have different 'worlds', each with their own levels, and I wanted to be able to allow for branching paths, and 'roads' that turned.
What I came up with was to define all the nodes on a map in another JSON file, including any 'pass-through' nodes.
  {"world":0,"id":0,"level":0,"neighbors":[-1,-1,-1,1], "x":0, "y":0},
  {"world":0,"id":1,"level":1,"neighbors":[-1,-1,0,2], "x":1, "y":0},
  {"world":0,"id":2,"level":-1,"neighbors":[1,-1,-1,3], "x":2, "y":0},
  {"world":0,"id":3,"level":2,"neighbors":[2,4,-1,7], "x":2, "y":1},
  {"world":0,"id":4,"level":-1,"neighbors":[3,5,-1,-1], "x":2, "y":2},
  {"world":0,"id":5,"level":-1,"neighbors":[4,6,-1,-1], "x":3, "y":2},
  {"world":0,"id":6,"level":3,"neighbors":[5,-1,-1,-1], "x":3, "y":3},
  {"world":0,"id":7,"level":4,"neighbors":[-1,-1,3,-1], "x":6, "y":1}

This is what I have right now for the first map in the game, which uses those first 5 levels.

world = which world map this node is on
id = the id of this node
level = which level this node points to - the '-1's are 'pass-through' nodes.
neighbors = this is an array of the node-ids that this node directly connects to. I'll explain this more in a minute.
x and y = the position of this node on the map

I load these nodes in and build my map by using the x,y values.
It ends up looking something like this:

(I added the Blue lines and numbers for reference)

So, working out the 'neighbors' was really tricky. The array for 'neighbors' goes: UP, DOWN, LEFT, RIGHT. So, if you look at that first record: '[-1, -1, -1, 1]' it says that the first node #0 (which is at '0,0') has no neighbors UP, DOWN, or LEFT, but RIGHT points to node #1.

If the player is on node #0, and they hit RIGHT, they will move to the right, and end up at node #1.
node #1 says that it has a neighbor to the LEFT (#0, which we know about already), and a neighbor to the RIGHT (#2).
node #2 however is a pass-through node. It says that it has a neighbor UP (#1) and to the RIGHT (#3) So, when the player is on #1 and they hit RIGHT, it see that they should move to node #2, which it to the right, but, once they get there, the pass-through node looks at where they came FROM (they came from the RIGHT), and immediately sends them to that neighbor, which is #3. Node #3, though, is DOWN from node #2.

From node #3, if they hit UP, it goes to node #2, and, since node #2 sees that it's UP neighbor = 1, it sends them to the LEFT, over to node #1.

This works pretty great! In addition to the stuff in the JSON file, I have a few properties of the level such as if it's unlocked or beaten or not, which, depending on the flag, will prevent the player from moving along a path. Also, if the player is on a level node, they can hit FIRE to start that level, and it properly launches the PlayState - loading the map and everything.

So, the game is coming along! I'm going to try to work on the different enemies, level conditions, game over/level clear screens, and upgrade menus next.

I wonder if I should start looking for an artist yet...

Pages: [1]
Jump to:  

Theme orange-lt created by panic