From 57fe8f3c4124819b95164547333a33f4c45eac8d Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Sun, 10 Mar 2019 12:07:40 -0400 Subject: Editor now allows tile placement You can scroll through the three layers (map, track, object) with Z/X. You can swap between focusing on the map and the tileset with TAB. You can place tiles with enter or space. Pretty rudimentary, but it's a start. --- src/editor.cpp | 246 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 235 insertions(+), 11 deletions(-) (limited to 'src/editor.cpp') diff --git a/src/editor.cpp b/src/editor.cpp index 92c6b67..30dde45 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -5,27 +5,150 @@ void Editor::tick( double dt, const Uint8* keystate) { + if (keystate[SDL_SCANCODE_LEFT] || + keystate[SDL_SCANCODE_UP] || + keystate[SDL_SCANCODE_RIGHT] || + keystate[SDL_SCANCODE_DOWN]) + { + // If the player is holding down a directional key, accumulate the time + // since the last tick, and then apply the directional key as many times as + // needed. The input lag class automatically handles the delays necessary + // for key repeat. + inputLag_.accumulate(dt); -} + while (inputLag_.step()) + { + if (mapFocus_) + { + // If we are focused on the map, move the map cursor. + if (keystate[SDL_SCANCODE_LEFT] && cursor_.x() > 0) + { + cursor_.x()--; + } -void Editor::render(SDL_Renderer* ren) -{ - if (!background_) + if (keystate[SDL_SCANCODE_UP] && cursor_.y() > 0) + { + cursor_.y()--; + } + + if (keystate[SDL_SCANCODE_RIGHT] && + cursor_.x() < level_.getSize().w() - 1) + { + cursor_.x()++; + } + + if (keystate[SDL_SCANCODE_DOWN] && + cursor_.y() < level_.getSize().h() - 1) + { + cursor_.y()++; + } + } else { + // If we are focused on the tileset, rotate through the selection of + // tiles. + if (keystate[SDL_SCANCODE_UP]) + { + selectedTile_--; + } else if (keystate[SDL_SCANCODE_DOWN]) + { + selectedTile_++; + } + + selectedTile_ %= level_.getTileset(layer_).getNumTiles(); + } + } + } else if (inputLag_.isActive()) { - surface_ptr bgSurf(IMG_Load("../res/editor_bg.png")); + // If the player is not holding down a directional key, reset the input lag. + inputLag_.reset(); + } + + // Check for keypress changes since the last tick. + input_.tick(keystate); - if (!bgSurf) + if (input_.wasPressed(SDL_SCANCODE_Z)) + { + switch (layer_) { - throw img_error(); + case Layer::map: + { + layer_ = Layer::object; + + break; + } + + case Layer::track: + { + layer_ = Layer::map; + + break; + } + + case Layer::object: + { + layer_ = Layer::track; + + break; + } } - background_.reset(SDL_CreateTextureFromSurface(ren, bgSurf.get())); - bgSize_ = { bgSurf->w, bgSurf->h }; + selectedTile_ = 0; + + // Reset the cached map so that it gets redrawn with the focused layer. + renderedMap_.reset(); + } else if (input_.wasPressed(SDL_SCANCODE_X)) + { + switch (layer_) + { + case Layer::map: + { + layer_ = Layer::track; + + break; + } + + case Layer::track: + { + layer_ = Layer::object; + + break; + } + + case Layer::object: + { + layer_ = Layer::map; + + break; + } + } + + selectedTile_ = 0; + + // Reset the cached map so that it gets redrawn with the focused layer. + renderedMap_.reset(); + } else if (input_.wasPressed(SDL_SCANCODE_TAB)) + { + mapFocus_ = !mapFocus_; } - for (int y = 0; y < WINDOW_SIZE.h() / bgSize_.h(); y++) + if (mapFocus_) { - for (int x = 0; x < WINDOW_SIZE.w() / bgSize_.w(); x++) + if (keystate[SDL_SCANCODE_RETURN] || + keystate[SDL_SCANCODE_SPACE]) + { + level_.at(cursor_.x(), cursor_.y(), layer_) = selectedTile_; + + // Reset the cached map so that it gets redrawn with the new tile. + renderedMap_.reset(); + } + } +} + +void Editor::render(SDL_Renderer* ren) +{ + // Tile the background art. + for (int y = 0; y <= WINDOW_SIZE.h() / bgSize_.h(); y++) + { + for (int x = 0; x <= WINDOW_SIZE.w() / bgSize_.w(); x++) { SDL_Rect rect { x * bgSize_.w(), @@ -37,4 +160,105 @@ void Editor::render(SDL_Renderer* ren) SDL_RenderCopy(ren, background_.get(), nullptr, &rect); } } + + // Render and cache the map if the cache is currently empty. + if (!renderedMap_) + { + renderedMap_.reset( + SDL_CreateTexture( + ren, + SDL_PIXELFORMAT_RGBA8888, + SDL_TEXTUREACCESS_TARGET, + LEVEL_SIZE.w(), + LEVEL_SIZE.h())); + + // Render each layer separately, then compose them atop each other. Layers + // above the currently selected one are drawn semi-transparently. + texture_ptr mapRender = level_.render(ren, Layer::map); + texture_ptr trackRender = level_.render(ren, Layer::track); + texture_ptr objectRender = level_.render(ren, Layer::object); + + if (layer_ < Layer::track) + { + SDL_SetTextureBlendMode(trackRender.get(), SDL_BLENDMODE_BLEND); + SDL_SetTextureAlphaMod(trackRender.get(), 127); + } + + if (layer_ < Layer::object) + { + SDL_SetTextureBlendMode(objectRender.get(), SDL_BLENDMODE_BLEND); + SDL_SetTextureAlphaMod(objectRender.get(), 127); + } + + SDL_SetRenderTarget(ren, renderedMap_.get()); + SDL_RenderCopy(ren, mapRender.get(), nullptr, nullptr); + SDL_RenderCopy(ren, trackRender.get(), nullptr, nullptr); + SDL_RenderCopy(ren, objectRender.get(), nullptr, nullptr); + SDL_SetRenderTarget(ren, nullptr); + } + + // Copy the rendered map onto the editor. + SDL_Rect mapLoc { + static_cast(BORDER_SIZE.w()), + static_cast(BORDER_SIZE.h()), + static_cast(LEVEL_SIZE.w()), + static_cast(LEVEL_SIZE.h()) + }; + + SDL_RenderCopy(ren, renderedMap_.get(), nullptr, &mapLoc); + + // If the map is focused, draw an outline around it. + if (mapFocus_) + { + SDL_SetRenderDrawColor(ren, 255, 0, 0, 255); + SDL_RenderDrawRect(ren, &mapLoc); + } + + // Draw a box indicating the position of the map cursor. + vec2s cursorLoc = BORDER_SIZE + TILE_SIZE * cursor_; + + SDL_Rect cursorRect { + static_cast(cursorLoc.x()), + static_cast(cursorLoc.y()), + static_cast(TILE_SIZE.w()), + static_cast(TILE_SIZE.h()) + }; + + SDL_SetRenderDrawColor(ren, 255, 0, 0, 255); + SDL_RenderDrawRect(ren, &cursorRect); + + // Draw the tileset for the currently selected layer. + SDL_Rect tilesetLoc { + static_cast(BORDER_SIZE.w() * 2 + LEVEL_SIZE.w()), + static_cast(BORDER_SIZE.h()), + static_cast(TILE_SIZE.w()), + level_.getTileset(layer_).getSize().h() + }; + + SDL_SetRenderDrawColor(ren, 255, 255, 255, 255); + SDL_RenderFillRect(ren, &tilesetLoc); + + SDL_RenderCopy( + ren, + level_.getTileset(layer_).getImage().get(), + nullptr, + &tilesetLoc); + + // If the tileset is focused, draw an outline around it. + if (!mapFocus_) + { + SDL_SetRenderDrawColor(ren, 255, 0, 0, 255); + SDL_RenderDrawRect(ren, &tilesetLoc); + } + + // Draw a box indicating which tile is currently selected. + SDL_Rect tileCursorRect { + tilesetLoc.x, + static_cast((1 + selectedTile_) * TILE_SIZE.h()), + static_cast(TILE_SIZE.w()), + static_cast(TILE_SIZE.h()) + }; + + SDL_SetRenderDrawColor(ren, 255, 255, 0, 255); + SDL_RenderDrawRect(ren, &tileCursorRect); } -- cgit 1.4.1