Frogger project going forward

Of course I forgot to update when I meant to. The project is going forward. We now have correct background colors and the purple sidewalks are in place. Since we have a sprite sheet, we figured the easiest way to draw the sidewalks was to make a class for the sidewalk tile, and make several instances of that class. The frog can be moved using the arrow keys, but there is no animation. We decided to postpone implementation of all features that aren’t absolutely necessary.

We also have a moving car, but we need to develop the system that will handle the spawning of those cars. There was a discussion on this because problems arose: since every car is an instance of the same class, there is no simple way for the manager class to tell them apart, so the easiest way to handle the cars is to make each car move and get destroyed when it disappears outside the screen. It can send a message to the GameState class so it can keep track of how many number of cars are on the screen. The reason we were hesitant to use this method is that we used to draw objects in the same order they were created, and if the game destroys and creates new cars, the frog will no longer be drawn on top like we wanted to. So I changed our draw function to draw on different depths. Three different is all we need: bottom for the background tiles, top for the frog, and middle for all other objects. This was achieved with a public method in each entity that returns the depth of that particular object: one of three enum values. Then I changed the drawing loop to what can be seen below.


void GameState::Draw()
{
    m_systems.draw_manager->DrawBackground(m_systems.width, m_systems.height);

    // Only for clarity. Datatype enum 'EDepth' could cast automatically to 'unsigned int'.
    unsigned int bottom = static_cast<unsigned int>(DEPTH_BOTTOM);
    unsigned int middle = static_cast<unsigned int>(DEPTH_MIDDLE);
    unsigned int top = static_cast<unsigned int>(DEPTH_TOP);

    // Inner loop draws all entities of a certain depth. Outer loop repeats the process for each depth.
    for (unsigned int drawDepth = bottom; drawDepth <= top; drawDepth++)
    {
        for (unsigned int i = 0; i < m_entities.size(); i++)
        {
            if (static_cast<unsigned int>(m_entities[i]->GetDepth()) == drawDepth) // Cast would also here happen automatically.
            {
                Sprite* sprite = m_entities[i]->GetSprite();
                if (sprite)
                    m_systems.draw_manager->Draw(sprite, m_entities[i]->GetX(), m_entities[i]->GetY());
            }
        }
    }
}

Advertisements

Fifth weekly programming post

OK, so the naming scheme of my “weekly” programming posts seemed like a good idea when I was still positive I would actually write a post each week. I am going to refer to this as the fifth post because it is my fifth week of programming; and a mismatch between these two numbers is prone to make me terribly confused in the future, should I ever come back to read an old blog post for whatever reason. I’m foreseeing like that. (It may also have the effect that it seems like I actually was ambitious enough two write the second, third and fourth posts, but they were then lost in cyberspace for reasons beyond my control.) Anyway, this seems like a good time to resume the blogging since I have just started making my first game. It will be made in Visual Studio using SDL2 and shamelessly imitate the classic arcade game Frogger. (Note that the reason I don’t feel any shame is not because I’m a bad person but because copying a classic game was part of the assignment.) I have a teammate by the way. We have started writing the basic engine for the game, following the structure of the engine live-coded by our teacher in class. What I find most difficult to grasp is the structure of the engine: what goes in which class and why. I constantly get the feeling that while I understand the code written by the teacher, I could not write it myself from scratch and get all the class relations to work. The plan, however, is that the deeper understanding will come when I start adding functions to the program, thus being forced to use the structure of the engine as opposed to just looking at it from outside.

From now on, I will try to update properly every week with the additions we make to the game, with examples of code in the posts.

Programming update

So here is the finished guessing game. I should have posted it way earlier because it already feels like I could do it better with the knowledge from the first lectures of this week. But I figure this is too basic a game to put any more time into, because regardless how perfect, it will always be a boring game to play.


#include <iostream>
#include <time.h>
#include <stdlib.h>

int random(int min, int max)
{
    return min + (rand() % (max - min + 1));
}

int main(int argc, char* argv[])
{
    int tries = 0;
    srand((unsigned int)time(0));
    int randomnumber = random(1, 100);
    bool victory = false;
    std::cout << "Guess the number between 1 and 100." << std::endl << std::endl;
    
    //std::cout << "random(): " << randomnumber << std::endl;

    while (true)
    {
        int guess = 0;    
        std::cin >> guess;

        if (guess >= 1 && guess <= 100)
        {
            if (guess == randomnumber)
            {
                std::cout << "Correct! You win! ";
                tries++;
                break;
            }

            else if (guess < randomnumber)
            {
                std::cout << "Too low. Try again.\n" << std::endl;
                tries++;
            }

            else if (guess > randomnumber)
            {
                std::cout << "Too high. Try again.\n" << std::endl;
                tries++;
            }
        }

        else
        {
            std::cout << guess << " is not between 1 and 100, stupid! Counts as a guess anyway.\n" << std::endl;
            tries++;
        }
    }

    if (tries == 1)
    {
        std::cout << "And on the first guess, too! You're a natural!\nPress Enter to exit.\n";
    }
    
    else
    {
        std::cout << "You needed " << tries << " guesses. Press Enter to exit.\n" << std::endl;
    }

    std::cin.ignore(1024, '\n');
    std::cin.get();
    return 0;
}

Featured image

First weekly programming post

This week has been the first week of the “Game Programming I” course. Since the course doesn’t require any previous knowledge of programming, the material has been pretty basic so far. Which suits me well, I realize now. I have a tiny bit of programming experience from playing around in GameMaker years ago, but GameMaker has its own programming language which in my opinion is a lot easier to use than the more powerful “C++” we are learning now. Even the basic stuff gets complicated when you actually start working with it yourself, as opposed to listening to it in a lecture. We got a bunch of exercises to do for practice of which the last one was the most comprehensive: to make a (ridiculously) simple guessing game. The game is played by typing numbers, guessing on a number between 1 and 100. After each incorrect guess, the game tells the player whether the guess was too high or too low. A correct guess results in a congratulation as well as a display of how many guesses were needed to get to the right answer, after which the only option is to exit the game. Deadly simple, right? Nope. My “game engine” is perfectly functional only without the random generation of a number, which sadly is the very core of the game. Apparently, generating a random number is not as simple as it sounds, and code for this was included in the sheet of exercises; code which I happily copied into my project; code which I still can’t get to work properly. I originally planned to finish all the exercises before writing this post, but alas; after a while of battling the error messages with everything I’ve got (desperately Googling bits of the randomization code), I have now decided to postpone the completion of the game until tomorrow, when I will have time to thoroughly go through the randomization code and actually understand it completely. Which I obviously should have done from the start. Lesson learned.

A proper update with the finished guessing game will follow. Pre-order now and play it on release day! Or something.