Sign in to follow this  
Outermedia

Canvas Tilemaps - Javascript Help

Recommended Posts

Ello guv'nors!

GOOGLE HAS FAILED ME!
I got some dumb probably really easy javascript things I'm stuck with and I'm in an endless loop of eh?

So I've got the this array 
0 = wall = cant move into
1 = path = can move into

* white 1 = player start point

var gamemap = [
    0, 0, 0, 0, 0,
    0, 1, 1, 1, 0,
    0, 1, 0, 0, 0,
    0, 1, 1, 1, 0,
    0, 0, 0, 0, 0,


im also abit lost on how to make the character 
use a nested array two values on each?
merge two arrays together? concat? idk...

use of north east south west buttons that move the player one array over?


on the click of a button CHECK
show text saying if can or cant go in direction because wall etc


Anyone fancy pointing me towards the right direction?

If this makes any sense.

Share this post


Link to post
Share on other sites

I'm not at all clear on what you're asking for?

Do you want to know how to reference a 2 dimensional point (i.e. something like [1, 5]) from  a 1 dimensional array? or whether you should represent your map as a nested (i.e. a 2 dimensional) array?

Or something else?

Share this post


Link to post
Share on other sites

Neither am I rereading it.
It was a long night staring into a screen.

What sense I can make of it is... 
How would I make a character?
How do I place the character in said array?
How do i then move the character up down left right but also allowing text to tell you which direction it has gone? And if it can or cant go that way due to wall.

As for the nested array I think my idea was that I can store more data (player) and the player array thing moves around. 

1= path, player, monster
 

So that when the player moves into the tile 
It could be 
2= path , monster

move player into nested array

2= path, player, monster

trigger fight blah blah

 

Hope that sort of clears it up a little.

Share this post


Link to post
Share on other sites

Yeah I know that feeling of being beaten down by a problem to the point where its difficult to even express it! It's usually a clue for a good nights sleep and to be tackled again when fresh!!

I think I know what sort of thing you're after.

How to express a tile and entity map has about as many solutions as there are developers out there! A common starting point might look the following:

So, your map might be a 5x5 2d grid of locations, to simplify things lets express tile types as integers, 1 is a wall, 0 is floor and to simplify our rules even further, you can step on the floor but not on the wall:

var map = [
  1, 1, 1, 1, 1,
  1, 0, 0, 0, 1
  ...
]

var width = 5

function get (x, y) {
  return map[x * (y + width)]
}

This is a simple 1d representation of a 2d tile map with an associated getter function to convert 2d to 1d (which requires knowing the width of the grid), note that [0, 0] is top-left, x going right, y going down (yes, coordinate systems are important but we've just chosen the "easiest" representation).

Now you need some sort of entity object (you might call it a class, but thats a bit ho-hum in JS):

var player = {
  x: 1,
  y: 1
}

You might want to add this player to an array of entities (or, even, an array of alive entities, depends what you want).

This is about all your renderer needs to get rendering, throw the map array and the width and tell it to draw, then draw your entity on top in the correct location.

To handle collision detection lets do something really simple, the following is semi-pseudo code:


function checkMapCollision (x, y) {
  var target = get(x, y)
  return target === 0
}

function handleMapCollision (entity, desired) {
  var isOkToMove = checkMapCollision(entity.x + desired.x, entity.y + desired.y)

  if (!isOkToMove) {
    return
  }

  entity.x += desired.x
  entity.y += desired.y
} 

function onKeydown (key) {
  if (key === 'left') {
    handleMapCollision(player, {x: -1, y: 0})
  }

  ...
}

Something like this would work (I've done it quickly, might have made a stupid mistake). Attach the `onKeydown` function to a keyboard (or joystick, or mouse, or touch, whatever) handler which responds to a key press event, takes the player entity and checks for a collision with the desired location, if all is ok then it updates the entity position so you either need to re-render or if you're using some sort of rendering loop then the position will update on the next render tick.

This is pretty much the basis of it. Your next requirement is to check for collisions with entities, you pretty much do the same but rather than a spatial look up against a grid you'd probably want to loop over all active entities and check to see if any of them currently occupy the desired target location, if they do then run a function that handles what should happen when that collision occurs, otherwise loop through the map spatial check (above) and see if the desired target location is ok on the map or not.

That really is about it, most other systems just add complexity on top of this simplistic model (obviously this is a very mature field pretty much as old as computer gaming, which isn't much younger than computing!).

Some stuff you might want to look at doing:

* Sometimes its easier to use [x, y] rather than `entity.x` and `entity.y`

* Integers are fine for representing tiles and/or entities but you'd want another lookup table that maps that integer to an object which represents the actual object i.e. a wall object might have a flag (boolean) saying it is impassable, whereas a water tile might have a flag that states only flying, swimming or floating entities can enter it etc etc etc.

* You might want to forego the integer (id) representation and just embed whole objects into your map and/or entity array but consider how distinct each element is i.e. if ALL of your walls are the same in a map and your map contains thousands of them then thats a load of memory you don't need to consume, just keep one wall object somewhere and your map array just references it.

* If some of your map entities do differ from the blueprint/template for, say, a wall object, maybe you only want to store the differences.

* The suggestion above notes looping over your entire entity array to find collisions, with 1000's of entities all moving this is expensive. You might want to look at techniques such as Octrees to simplify the search space (this gets technical real fast! but if you're diving in, then dive in!), if you want a warm-up maybe read up on A/B (or Black-Red trees) as Octrees are a more advanced (extra dimension/s) version, again, this gets technical real fast! I'd say its key learning for any developer!

* Consider using a 2d array (or, an array or arrays) to hold your data, personally I dislike this approach but you might find it easier to use `map[0][1]` rather than using a getter.

* Think about what to do when you have a collision, do you want a handler that takes the two 'things' that are colliding which decides what to do? i.e. this handler would map a collision between player and wall to a function, between player and enemy to another etc etc etc. As your list of possible colliders grows this can get tricky to manage, so maybe make it a little more interesting and physics based by considering the 'stuff' that makes up objects i.e. if 2 objects are marked as solid then they can't occupy the same space.

* The above precludes entities occupying the same space, but maybe you want that.

* The above also assumes only 1 single tile occupies a location, maybe you want multiple tiles on a location, so maybe each location holds an array of tiles at that location, or maybe you want a linked-list if your other dimensions are sparse?

* If your map becomes an array of locations, which each hold and array of 'things' on that location, maybe you don't need the entity array anymore and they can just live in the map. In some ways this simplifies things, in other it makes things trickier.

 

Hope that helps you get clear which way you want to implement things, I'd say that if you're not sure have a play with various techniques, personally I love playing with 2d map representations and systems, maybe you will too!

Share this post


Link to post
Share on other sites

thank you for this

starting from a basic level is very hard to find a way to explain what you mean in any question but im gonna spend my time rereading it over and over because it makes things very clear, alot of things I have read just go over my head and im like wah?

and even trying to change one slight thing from what you read/watch can seem boggling because none of it went into a simple explaintion.

helping already lol as lover of civilisation and other games similar i already love it just need to understand it fully now.
 
 


 

Share this post


Link to post
Share on other sites

I think the first distinction to make is to separate tilemap data from entity data, this makes things a little easier conceptually.

Have one array for the tilemap and some functions to help you access it and do stuff like changing an entry or building it initially. If you're building a civ-like game then the tilemap is largely immutable (it doesn't change) so you can just generate your map structure and only worry about accessing parts of it to render it i.e. if it is bigger than your screen area then you probably only want to render visible bits.

Keep your entity array separate for now and have different functions for accessing it and manipulating it.

Your render method will loop over the visible portion of your tilemap and render it and then loop over your visible entities and render them.

Share this post


Link to post
Share on other sites

What sort of problems?

var player = {
  position: [0, 1],
  health: 200,
  attack: 12
}

Or, maybe you want to use a function to do it (often called a factory as it churns out new objects):

function createEntity (name) {
  if (!name) {
    throw new Error('Entities need a name')
  }

  return {
    name: name,
    position: [0, 0],
    health: 10
  }
}

var entities = []

for (var x = 0; x < 10; x++) {
  entities.push(createEntity('entity' + x))
}

This way creates a list of 10 entities, which are all pretty much the same but that's the base, build out from there.

I expect what you're having issue with is how to structure your data, and I agree, that's tough.

Try first with an immutable tile map, that's your background (this is just a tilemap you create once at the start and don't touch).

Then create another array of entities.

I think this is probably easiest to get going, sure, you might find some problems with this approach but I think you probably just need to get cracking with a system. Build it this way, discover the pros/cons. Build it another way and do the same.

Once you've done this a few times you'll be in a far better position to make decisions on the 'best' data representation for your use-case. It very much takes experience.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.