Shinrai

Members
  • Content count

    9
  • Joined

  • Last visited

Community Reputation

0 Neutral

About Shinrai

  • Rank
    Newbie

Personal Information

  • Interests
    Art
    Design
    DevOps
    Education
    Programming
  1. How do I Script NPC's? (C++)

    Right, I do already have some sort of API made. As I've said in the question, I'm able to move the NPCs around, and eventually, I'll be able to make them talk. My issue lies in things like timing and how I can actually assign these individual scripts to the NPCs. When I say timing, I mean that it take 16 frames for the NPC to move one tile, and so I don't want to go through every instruction frame by frame. I can't figure out a proper way to time that. About assigning a script to the NPCs, I'm sure I can make the NPC object take in a filepath for the script in the constructor. But then what? What do I do with that? If possible, do you think you could add any sort of example? Thanks again.
  2. How do I Script NPC's? (C++)

    I've been wanting to figure out a proper method to script NPC's for my game engine. The NPC object class contains simple methods to draw, update, and move the character (Other methods for dialogue will be added on later). The problem is that, of course, they don't do anything. These characters need some sort of script. But I can't figure out anyway I can each assign these to each NPC. By scripting, I mean something that would look like this. A file that I could assign each NPC so that they follow the script. moveWest(3); // Move in the west direction for 3 tiles followPlayer(); // Start following the player speak("Hello there!") // Talk to the player It won't look exactly like that, but that's something similar to what I want to accomplish here. I know there are some methods out there, but I need a proper method that I could use for my situation. I don't know how useful this information is going to be, but I want to make it clear that my NPC's update function is updated based on frames. Basically, the function runs 60 times every second, the speed that my game engine is also running at. If any other additional information is needed, let me know. I appreciate any help with this.
  3. C++ and SDL2 Tile Collision

    This method works great, but I am running into an issue. When the player moves to the edge of the map, the game crashes because of a segmentation fault. I'm guessing this is because an array index that doesn't exist is being checked. Anything you think I could do about that? Side note: Yeah, I'm using that exact method to draw in order to improve performance.
  4. C++ and SDL2 Tile Collision

    And I've already reached the limit. Making a map that has 40 by 36 tiles already slows the game down to a mere 17 frames per second. I can't blame the processor though, doing 1440 tile checks for 3 entities is 4320 tile checks 60 times every second. I guess I'll have to look into optimizing the code using another one of these methods.
  5. C++ and SDL2 Tile Collision

    After some research into this, I've found a way that works for me. I'll post it just in case anyone else would like to possibly use it. However, I don't think it is the best approach, it may be quite resource intensive. The system involves creating a one dimensional vector containing tile objects. std::vector<Tile*> map; Each tile object contains an SDL_Rect that contains information for the tile's height, width, and x and y positions. It also contains a tile ID which is used to match up to the tileset I'm using. Since every tile contains separate information for its position, the map can just be rendered by cycling through the vector and rendering every tile based on what position it has. As for collision, the same sort of thing is done. Collision detection involves cycling through every tile in the map in order to see if the player is colliding with a certain tile ID. bool touchesWall(std::vector<Tile*> map) { for (int i = 0; i < map.size(); i++) { if (map[i]->getTileID() == 1) { if (checkCollision(player_rectangle, map[i]->getTileRectangle())) return true; } } return false; } The checkCollision function takes two rectangles and compares them to check whether they are colliding or not. So in this case, I would check both the player's collision rectangle and the rectangle of whatever tile I'm checking. bool checkCollision(SDL_Rect a, SDL_Rect b) { int leftA, leftB; int rightA, rightB; int topA, topB; int bottomA, bottomB; leftA = a.x; rightA = a.x + a.w; topA = a.y; bottomA = a.y + a.h; leftB = b.x; rightB = b.x + b.w; topB = b.y; bottomB = b.y + b.h; if (bottomA <= topB) return false; if (topA >= bottomB) return false; if (rightA <= leftB) return false; if (leftA >= rightB) return false; return true; } Although this works fine for what I'm trying to do. I can't help but think about how straining that might be on the processor to be doing every frame. For such a simple game, I don't want it taking up too much power for each entity on the screen. For anyone who is wondering, this method comes from the LazyFoo tiling tutorial. http://lazyfoo.net/tutorials/SDL/39_tiling/index.php
  6. C++ and SDL2 Tile Collision

    I'm having trouble figuring out how to accomplish tile collision with SDL2 and C++. I have a 2D map vector which contains either a 1 or a 0 for each index. std::vector<std::vector<int> > map; That map contains data for which tiles can be collided with and which tiles cannot. Below is an example of what it could look like. {{0, 1, 0, 1, 0}, {1, 0, 1, 0, 0}, {0, 0, 0, 1, 0}, {0, 1, 1, 1, 0}, {1, 0, 0, 0, 1}} I also have a player class which contains some simple update, draw, move, etc. functions. All the player's logic takes place in the update function. The player's position information is stored in an SDL_RECT like so. SDL_RECT player_rectangle; player_rectangle.x = 0; player_rectangle.y = 0; player_rectangle.w = 16; player_rectangle.h = 16; As you may know by now, each tile in this game is 16 by 16 pixels. And movement in the game is tile-based. In the update function, I'm able to correct collisions with the edge of the map like so. void update() { // Process movement if (player_rectangle.x < 0) player_rectangle.x = 0; if (player_rectangle.x > map_rectangle.w - 16) player_rectangle.x = map_rectangle.w - 16; if (player_rectangle.y < 0) player_rectangle.y = 0; if (player_rectangle.y > map_rectangle.h - 16) player_rectangle.y = map_rectangle.h - 16; } My issue with understanding how to do this lies in the fact that the player's position is measured in pixels, while the map's tiles are measured as a grid, each index being 16 by 16 pixels. I've tried dividing the player's position by the tile's size in order to convert it to a grid so that I could try something similar to this. if (map[player_rectangle.y / 16][player_rectangle.x / 16] == 1) // Correct collision But this doesn't work all the time since the player's x and y positions aren't always factors of 16 when the player is moving between tiles. In fact, I can't even figure out how I would correct this collision even if I could figure out how to map out the player's position to the collision map. I'm aware this probably isn't the best approach, so I'm open to better ideas for accomplishing this.
  7. I'd be fine with using the fixed timestep method that you're talking about. It just doesn't seem like the standard though. Do many people use this? If so, how do they manage to keep up a constant framerate on lower end systems that may require a lower one? You can't just switch the frame rate if everything is based on frames, you'd have to change a lot of things in the game before it ran at the proper speed.
  8. I've actually done something using two boolean variables. isMoving checks whether the player is currently moving, if they player is moving, no input will be taken. The other variable atTarget checks whether the player has reached the target tile or not. If the player is atTarget and isMoving, the player will stop (Meaning isMoving and atTarget are both set to false). This works ok, but it's buggy and results with a frame skip, making the player look jittery. This is basically how the logic works. It has to really be fixed up, but I hope you understand where I want to go with it. void update(int elapsed_time_ms) { if (isWalking == true && atTarget == false) { // Update player movement } // Check if the player has reached the target if (player_x == targetX && player_y == targetY) atTarget == true; // Stop movement if (atTarget == true && isWalking == true) // Stop walking (isWalking == false) } // Just one direction for a basic example void moveRight() { if (!isMoving) { isMoving = true; atTarget = false; targetX += 16; velocityX = speed; } } This code really has to be cleaned up. Movement is buggy and it causes the player animation to stutter every time they walk over a tile. Also, if the player goes even 1 pixel over the target, they continue moving without being able to stop. Which kinda sucks.
  9. I've been wondering how to work out the logic for creating smooth tile-based movement for a player. These are the functions being used to handle player movement as of now. (Input and animation is already being handled, but not in the code. I just want to show the basics of how the logic works for now.) void Player::startMovingUp() { mVelocityY = -kWalkSpeed; mDirectionFacing = UP; } void Player::startMovingDown() { mVelocityY = kWalkSpeed; mDirectionFacing = DOWN; } void Player::startMovingLeft() { mVelocityX = -kWalkSpeed; mDirectionFacing = LEFT; } void Player::startMovingRight() { mVelocityX = kWalkSpeed; mDirectionFacing = RIGHT; } void Player::stopMoving() { mVelocityX = 0; mVelocityY = 0; } All of these values are updated in the player update function. (Everything is time-based, rather than frame-based. That's where the elapsed_time_ms variable comes in.) void Player::update(int elapsed_time_ms) { mX += round(mVelocityX * elapsed_time_ms); mY += round(mVelocityY * elapsed_time_ms); } This is perfectly fine to move the player around. But I want my player to be moving on a tiled map, locked to a grid, rather than just moving freely like this. Each tile in the game have fixed dimensions of 16 by 16 pixels. This may be important, so I'm just leaving it here.