Jump to content
  • Advertisement

Neometron

Member
  • Content Count

    53
  • Joined

  • Last visited

Community Reputation

606 Good

About Neometron

  • Rank
    Member

Personal Information

  • Role
    Artist
    Business Development
    Programmer
  • Interests
    Art
    Audio
    Business
    Design
    DevOps
    Education
    Production
    Programming
    QA

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. I'll try to clarify what I was doing in the Render pseudo code. I'll do it twice to show how it works. Round 1: void Render() { .. Get camera position in pixels camera_x = .. camera_y = .. chunk_id[4] = GetCameraChunks( camera_x, camera_y ) Let say the camera's origin is located at 960, 540. camera_x = 960 camera_y = 540 We'll look at the GetCameraChunks. BTW, remember when I said I didn't check my math; I didn't account for off by 1 problem so I forgot to subtract 1 to the maximums. chunk_id[4] GetCameraChunks( camera_x, camera_y ) { min_x = camera_x - SCREEN_HX max_x = camera_x + SCREEN_HX - 1 min_y = camera_y - SCREEN_HY max_y = camera_y + SCREEN_HY - 1 chunk_id[0] = pair< GetChunkCoord( min_x, min_y ) > chunk_id[1] = pair< GetChunkCoord( max_x, min_y ) > chunk_id[2] = pair< GetChunkCoord( min_x, max_y ) > chunk_id[3] = pair< GetChunkCoord( max_x, max_y ) > } min_x = 960 - 960 = 0 max_x = 960 + 960 - 1 = 1919 min_y = 540 - 540 = 0 max_y = 540 + 540 - 1= 1079 We'll also look at what GetChunkCoord does with these values. chunk_x, chunk_y GetChunkCoord( pixel_x, pixel_y) { chunk_x = pixel_x / CHUNK_SIZE chunk_y = pixel_y / CHUNK_SIZE } chunk_x = pixel_x / CHUNK_SIZE = 0 / 3200 = 0 chunk_y = pixel_y / CHUNK_SIZE = 0 / 3200 = 0 chunk_x = pixel_x / CHUNK_SIZE = 1919 / 3200 = 0 chunk_y = pixel_y / CHUNK_SIZE = 0 / 3200 = 0 chunk_x = pixel_x / CHUNK_SIZE = 0 / 3200 = 0 chunk_y = pixel_y / CHUNK_SIZE = 1079 / 3200 = 0 chunk_x = pixel_x / CHUNK_SIZE = 1919 / 3200 = 0 chunk_y = pixel_y / CHUNK_SIZE = 1079 / 3200 = 0 Note that this is normal behavior for division for integer types. So going back to GetCameraChunks: chunk_id[0] = pair< GetChunkCoord( min_x, min_y ) > = pair< 0, 0> chunk_id[1] = pair< GetChunkCoord( max_x, min_y ) > = pair< 0, 0> chunk_id[2] = pair< GetChunkCoord( min_x, max_y ) > = pair< 0, 0> chunk_id[3] = pair< GetChunkCoord( max_x, max_y ) > = pair< 0, 0> I'll skip ahead to this section of the Render function: ..Tile's pixel location in world space world_px = (TILE_SIZE * tile_x) + (chunk.id[x] * CHUNK_SIZE) world_py = (TILE_SIZE * tile_y) + (chunk.id[y] * CHUNK_SIZE) ..Camera's top left px coord in world space camera_px = camera_x - SCREEN_HX camrea_py = camera_y - SCREEN_HY ..Tile's pixel location in screen space tile_px = world_px - camera_px tile_py = world_py - camera_py world_px = (TILE_SIZE * tile_x) + (chunk.id[x] * CHUNK_SIZE) = ( 64 * 0 ) + ( 0 * 3200 ) = 0 world_py = (TILE_SIZE * tile_y) + (chunk.id[y] * CHUNK_SIZE) = ( 64 * 0 ) + ( 0 * 3200 ) = 0 camera_px = camera_x - SCREEN_HX = 960 - 960 = 0 camrea_py = camera_y - SCREEN_HY = 540 - 540 = 0 tile_px = world_px - camera_px = 0 - 0 = 0 tile_py = world_py - camera_py = 0 - 0 = 0 At this point render the tile at tile_px and tile_py which is top left corner of that tile image. Round 2: We moved the camera by 10px in the update function. camera_x += 10 = 960 + 10 = 970 camera_y += 10 = 540 + 10 = 550 GetCameraChunks( 970, 550 ) will yield again 4x pair<0, 0> world_px = (TILE_SIZE * tile_x) + (chunk.id[x] * CHUNK_SIZE) = ( 64 * 0 ) + ( 0 * 3200 ) = 0 world_py = (TILE_SIZE * tile_y) + (chunk.id[y] * CHUNK_SIZE) = ( 64 * 0 ) + ( 0 * 3200 ) = 0 camera_px = camera_x - SCREEN_HX = 970 - 960 = 10 camrea_py = camera_y - SCREEN_HY = 550 - 540 = 10 tile_px = world_px - camera_px = 0 - 10 = -10 tile_py = world_py - camera_py = 0 - 10 = -10 At this point render the tile at tile_px and tile_py which is top left corner of that tile image but partially off the screen. The conclusion is that horizontal and vertical scrolling is built into the formula. Just move the camera an the world will move with it.
  2. Here are my assumptions about your project: Unit of measurement is in pixels A tile is unit squared; 64x64px Top left screen coord is 0,0 and bottom right is 1919,1079; 1080p monitor Your 50x50 tilemap chunk is rendered from left to right, top to bottom Lets say your tiles are 64x64px and your chunk is 50x50 tiles, so a chunk would be 3200x3200px. Also for the time being, lets say chunk instances are stored in a 2D array. If the chunk is not loaded then the instance is invalid. Pseudo Code: TILE_SIZE = 64 CHUNK_SIZE = TILE_SIZE * 50 chunk_x, chunk_y GetChunkCoord( pixel_x, pixel_y) { chunk_x = pixel_x / CHUNK_SIZE chunk_y = pixel_y / CHUNK_SIZE } chunk GetChunk( chunk_x, chunk_y ) { chunk = chunks[chunk_x][chunk_y] } tile GetTile( pixel_x, pixel_y ) { chunk = GetChunk( GetChunkCoord( pixel_x, pixel_y ) ) if chunk is valid { tile_x = (pixel_x % CHUNK_SIZE) / TILE_SIZE tile_y = (pixel_y % CHUNK_SIZE) / TILE_SIZE tile = tilemap[tile_x][tile_y] } } Now for figuring out what chunks the camera sees. Since a chunk is 3200px squared, you can fit a 1920x1080 screen within a chunk. The most chunks you can physically see is 4 when the screen is at one corner of a chunk. SCREEN_X = 1920 SCREEN_Y = 1080 SCREEN_HX = SCREEN_X / 2 SCREEN_HY = SCREEN_Y / 2 chunk[4] GetCameraChunks( camera_x, camera_y ) { min_x = camera_x - SCREEN_HX max_x = camera_x + SCREEN_HX min_y = camera_y - SCREEN_HY max_y = camera_y + SCREEN_HY chunk[0] = GetChunk( GetChunkCoord( min_x, min_y ) ) chunk[1] = GetChunk( GetChunkCoord( max_x, min_y ) ) chunk[2] = GetChunk( GetChunkCoord( min_x, max_y ) ) chunk[3] = GetChunk( GetChunkCoord( max_x, max_y ) ) } Chunks should be referenced by chunk coord. I don't know what language you are using, however I bet there is some form of a map class for the language you are using. The chunk coord pair would be the map key and the map value would be the instance of your chunk. If there is no entry for the map key, the chunk is not loaded. If not loaded, load the chunk and create a key for the map. One trick to unload chunks is to have a timer countdown for chunks that are not within the camera view. The countdown could be set for a few minutes and when a chunk has any tiles rendered just reset the countdown. If the countdown hits 0, unload the chunk. I'm going to redefine function GetChunk and GetCameraChunks in my Pseudo Code class Chunk { id data cooldown } COOLDOWN_SECONDS = 180 map_chunks = map< ChunkID, Chunk > chunk GetChunk( chunk_x, chunk_y ) { chunk_id = pair<chunk_x,chunk_y> if map_chunk.contains(chunk_id) chunk = map_chunk.get(chunk_id) else chunk = invalid } chunk LoadChunk( chunk_id ) { chunk = new Chunk { id = chunk_id data = Tile[50][50] cooldown = COOLDOWN_SECONDS } .. fill chunk.data map.insert(chunk_id, chunk) } chunk_id[4] GetCameraChunks( camera_x, camera_y ) { min_x = camera_x - SCREEN_HX max_x = camera_x + SCREEN_HX min_y = camera_y - SCREEN_HY max_y = camera_y + SCREEN_HY chunk_id[0] = pair< GetChunkCoord( min_x, min_y ) > chunk_id[1] = pair< GetChunkCoord( max_x, min_y ) > chunk_id[2] = pair< GetChunkCoord( min_x, max_y ) > chunk_id[3] = pair< GetChunkCoord( max_x, max_y ) > } void Render() { .. Get camera position in pixels camera_x = .. camera_y = .. chunk_id[4] = GetCameraChunks( camera_x, camera_y ) ..Note chunk_id may have duplicate IDs previous_chunk = invalid for i in range(0, 4) { chunk = GetChunk(chunk_id[i]) if chunk not valid { chunk = LoadChunk(chunk_id[i]) } if chunk != previous_chunk { ..Note I'm just going to render everything in the chunk for tile_y in range(0, 50) { for tile_x in range(0, 50) { tile = chunk.data[tile_x][tile_y] ..Tile's pixel location in world space world_px = (TILE_SIZE * tile_x) + (chunk.id[x] * CHUNK_SIZE) world_py = (TILE_SIZE * tile_y) + (chunk.id[y] * CHUNK_SIZE) ..Camera's top left px coord in world space camera_px = camera_x - SCREEN_HX camrea_py = camera_y - SCREEN_HY ..Tile's pixel location in screen space tile_px = world_px - camera_px tile_py = world_py - camera_py .. Render the tile } } ..Reset chunk's unload timer chunk.cooldown = COOLDOWN_SECONDS } previous_chunk = chunk } } void Update( delta_time ) { for chunk in map_chunks { chunk.cooldown = chunk.cooldown - delta_time if chunk.cooldown < 0 { map_chunks.remove( chunk.id ) } } } I hope this helps. Good luck BTW: I didn't check any of my math, so there may be errors.
  3. Neometron

    WorldCubed

    These are images as I progress in making my own voxel engine.
  4. Neometron

    Week of Awesome III : Part One

    It's come near the end of day three for the WoA3, and I want to elaborate on what had happened since the start of the competition. Prior to the competition start: Circumstances broke my team up! I originally planned to work with my daughter and nephew, but they had other obligations this summer break. However, I will not be working alone since I have joined forces with Markypooch in team Pink Elephant. In this team I assumed my role as content creator where as Markypooch is the lead programmer. Day 1: We stayed up late Sunday night, drinking mainly, to wait for the competition's theme "Death is Useful." I find this theme interesting because it can be spun in so many different ways. I also found this theme to be difficult because it can be spun in so many ways. We called it a night and figured that we would have a solid idea later in the day. Evening came, and we still did not have a clue. Day 2: We determined that the game had to be simple, one level, no collisions or physics, and can be programmed while off work hours. While Markypooch was working at his day job, I drafted up a game concept in Blender. He liked it, and it is now game on! Day 3: My nephew may still help with sound effects. I tasked him to make about 30 sfx of various things. Here are screenshots of our level I been working on. Note that these are only renditions using Blender's cycles.
  5. I haven't been active on GameDev for a while now, so I suppose I'll make my first post. I decided to make the move from programming as a hobby to programming as a profession, so I started my own indie game development business last month named NeoVG.
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!