adrian17

Members
  • Content count

    11
  • Joined

  • Last visited

Community Reputation

200 Neutral

About adrian17

  • Rank
    Member
  1. Creating flexible behaviour without scripting?

      Actually, I have implemented something similar - for bullets with complex movements. Every complex bullet has its own vector of instructions which are executed at specified time frames. It's not perfect, since I would also love to make a bullet spawn other bullets with an instruction. Aside from that, I'm very happy with this.   That's how it looks like: //BasicEnemy::Logic() for(int i=0;i<360;i+=15) { bulletManager->AddEnemyComplexBullet(B_BULLET1, x, y, basev, i-a, 0, 0); bulletManager->AddEnemyBulletData(45, BULLET_ANGULAR_VELOCITY, SET, 5); bulletManager->AddEnemyBulletData(45, BULLET_ACCEL, SET, -0.7); bulletManager->AddEnemyBulletData(55, BULLET_ANGULAR_VELOCITY, SET, 0); bulletManager->AddEnemyBulletData(55, BULLET_ACCEL, SET, 0); } Anyway, that was the first thing I thought about when thinking about enemy behaviors, but unfortunately it won't work. That's simply because, no matter how complex the instruction is, it won't allow looping (...but I hope I'm wrong about that). If I want to shoot 100 bullets in a circle, writing 100 instructions for each shot makes no sense. That's exactly why I couldn't make the bullet spawn other bullets.   I don't really need to use states and respond to any behavior, because I don't need the enemies to respond to anything whatsoever. I just need a clean way to set a behavior once, when creating the enemy or declare it when the program begins and then assign it to enemy during its creation. (and as "behavior" I just mean either "at a given frame since creation, set/change velocity and direction" or "shoot a bullet/a lot of bullets in a given direction" OR "...with a random offset" OR "...in the player's direction" OR "in the player's direction with a random offset" OR ... )
  2. I'm creating a simple shmup from scratch. This is how my base Enemy class looks like: class Enemy { public: Enemy(int ntype, double nx, double ny, double nvx, double nvy): type(ntype), x(nx), y(ny), vx(nvx), vy(nvy) {}; virtual ~Enemy() {}; void Move(){x+=vx;y+=vy;}; virtual void Logic()=0; virtual void Draw(); bool IsDead(){return health<0;} void ReduceHealth(int damage){health-=damage;} SDL_Rect GetLoc(){return loc;} protected: int type; int health; double x, y; double vx, vy; SDL_Rect loc, source; void GetVectorToPlayer(double &x, double &y); double GetAngleToPlayer(); }; The Logic() function is the main function that defines the enemies' behaviours. It can influence both its movements and shooting patterns. For example, it may look like this:   double angle=GetAngleToPlayer(); if(globalFrameCounter%120==0) //will shoot every two seconds for(int i=-3;i<=3;i+=1) //will shoot seven bullets in the player's direction bulletManager->AddEnemyBullet(B_BULLET1, x, y, 5, angle+i); //bullet sprite, location, velocity and direction Finally, all the enemies are created on the vector via the manager, like this (I have only one BasicEnemy subclass for now, so the function will be expanded int the future): void EnemyManager::AddEnemy(int type, double x, double y, double vx, double vy) { enemies.push_back(std::unique_ptr<BasicEnemy>(new BasicEnemy(type, x, y, vx, vy))); } Now, my problem is, what if I want to have a lot of different types of enemy behaviours. In the current state, it would force me to write a separate subclass with a new Logic() function for every possible behaviour. That's obviously the wrong approach, since it would force me to create tens and tens of subclasses. I also don't want to use any scripting language like Lua, because I have no knowledge of them and it feels like using a sledgehammer to crack a nut. So... is there an easier way that I'm not seeing?
  3. Oh, I see... I was convinced that the only way to check the special keys was was by using event.key.keysym.mod, I didn't even try scanning it as any other key. Thanks a lot!
  4. Okay, thanks. It looks really nice, actually. I've used your example and moved all in-game input handling directly to Game::HandleEvents.Right now it's in a side branch Here. Unfortunately, I'm still having problems with scanning keymods. It's definitely my fault, but I don't know how to implement this properly. Right now my experiments looks like this: while(SDL_PollEvent(&event)) { SDLsystem->Input(); if( event.type == SDL_KEYDOWN ) { if(event.key.keysym.mod == SDLK_LALT) {SDL_SetWindowTitle(window, "alt down");} SDL_Keycode key=event.key.keysym.sym; if(key == SDLK_ESCAPE ) {nextState = State::MAINMENU;} //checking normal keys } else if(event.type == SDL_KEYUP) { if(event.key.keysym.mod == SDLK_LALT) {SDL_SetWindowTitle(window, "alt up");} SDL_Keycode key = event.key.keysym.sym; //checking normal keys } } And the key isn't detected at all.  If I change the operator in the statement to & (like shown in some code examples):  if(event.key.keysym.mod & SDLK_LALT) It detects Shift (?) being pushed and released but only when Ctrl is pushed at the same time (??). Something very similar happens if i try to detect the Shift key. How am I supposed to do it? It works properly when I try to check if Alt and Enter are pushed together, but not when I'm checking for Alt alone.
  5.   That sounds good, although with my current setup I can't make it work - I can pass SDLK values to the constructor, but the problem arises then I try to use it in the case statement - because case needs constant values to work with. It doesn't want to compile even when I define key values as const int. void Paddle::InputLeft() { if( event.type == SDL_KEYDOWN ) { switch( event.key.keysym.sym) { case keyUp: {vy =- basev; up=1;} break; //error: "this" it not a constant expression case keyDown: {vy = basev; down=1;} break; default: ; } } if( event.type == SDL_KEYUP ) { switch( event.key.keysym.sym ) { case keyUp: {up=0; if(down==1) vy=basev; else vy = 0;} break; case keyDown: {down=0; if(up==1) vy=-basev; else vy = 0;}; break; default: ; } } } (by the way, the above code shows why I don't think that the second approach you've shown would work with my current setup - in your code the paddle would stop moving as soon as any key release is detected - it would work fine until a player presses both keys at the same time and releases only one of them. That's why I've added the extra "if(down==1)" statements. ) I will think about this more, but I have some stranger issues right now, like SDL_SetTextureAlphaMod stopping working after toggling fullscreen/window and problems with detecting special keys (for some reason, shift key gets detected with a second of lag and its release isn't detected at all).
  6.   Thanks anyway. I guess the only thing left for me right now is asking at the SDL Forums.
  7. Still no improvement, with both your examples (the last one didn't cause any crashes). By the way, the sound plays properly every time. In the meantime I've recorded a video to better visualize what's going on: https://www.youtube.com/watch?v=qE9m0qHt6ls
  8. I'm sure that destructor is called - in fact, I can see Mix_FreeChunk; being called. If comment it out, the memory usage increases even faster.   That's actually quite strange - when the Mix_FreeChunk is called in the destructor, memory usage doesn't drop at all - it just influences how big the increase is when loading the WAV in the constructor. That means that the "leak" occurs when I try to load the sound into recently freed memory, am I right?   (by the way - I'm aware that i could just load the sound files when launching the game instead of loading them every time in the object constructor, but that's not solving the problem, that's getting around it. If I ever had a game with complex levels and wanted to load specific resources for each level, the problem would resurface)
  9.   I think it is, and I don't see any reason why it wouldn't be called. Memory usage didn't increase at all when I commented out all mixer-related functions. I'm also sure that the ball, board and paddle objects are destroyed.     I checked it - after switching between MainMenu and Game for a while, reported memory usage jumped from 13MB to 30MB and was still getting higher. Every time I started the game, it increased by approx. 100KB (sound files have a total size 94KB).
  10. Thanks! I've already pushed an update in which I added the ParticleManager class (in the particles.h file). I see what you mean - if I ever want to expand the particle system or make specific particle subclasses, it should make managing the code easier.   My new concern right now is, the Task Manager shows constant increase in memory usage every time I switch between Game an MainMenu. Looks like a probable memory leak, but I have yet to find it.   EDIT: I've found the leak: for some reason, when I use Mix_LoadWAV(); in the constructor and Mix_FreeChunk() in the destructor, the memory isn't freed completely. Strange...
  11. Hi! As the first step made a simple Pong game, both to get a bit of practice and to have a nice code foundation for future projects. I've used SDL2 and a tiny bit of sdl2_mixer, just to get the hang of it. I'm quite happy with the code, although I guess some things could have been done better, eg. file structure. The only thing I really don't like is how I had to divide paddle's input functions to InputRight() and InputLeft(), but I didn't know any other good way of doing this (aside from making subclasses for left and right paddle, which didn't seem worth the effort to me).   https://github.com/adrian17/pong (it's also my first time using Git, I hope I didn't mess anything up)   Regarding SDL, I have a few small "I have no idea why this happens" issues, mostly regarding toggling fullscreen with SDL_SetWindowFullscreen. For convenience, I've written these in my repo's "issues" section.