Attack on the Forest

The Partridge Family were neither partridges nor a family. Discuss.
albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Attack on the Forest

Post by albinopapa » February 19th, 2018, 8:27 pm

Aside from the CPU being in a breakable state ( able to be paused when hitting a break point ), you have more software sanity checks in debug mode. Plus there are few optimizations in place in debug mode compared to release mode.

I would compare debug mode to be like using an interpreter, which interprets the code line by line and converts to machine code before executing.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

User avatar
Zedtho
Posts: 189
Joined: February 14th, 2017, 7:32 pm

Re: Attack on the Forest

Post by Zedtho » February 19th, 2018, 8:40 pm

Thanks for answering albinopapa!

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Attack on the Forest

Post by albinopapa » February 19th, 2018, 11:11 pm

Welcome
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

User avatar
Zedtho
Posts: 189
Joined: February 14th, 2017, 7:32 pm

Re: Attack on the Forest

Post by Zedtho » February 20th, 2018, 10:27 am

Hey Albinopapa, I've got a question about your framework.
I'm trying to clamp all the characters in the game to the screen, but I've got one problem.
When new entities spawn to attack the character, they have to spawn a bit off-screen and walk towards the character. My question is if it's possible to specify what part of the sprite I want it to draw in your framework, as when it's in the process of getting onto the screen f.ex. only the second half of the sprite can be drawn. (So if I can specify a rectangle of the sprite that I want to draw).

I've got one other question that is less related to the framework. To check the collision of my characters I need to check if the rectangle of one of them is overlapping with the other. In what part of my code should I check this? In game.cpp or my User class? Or is the Entity (Enemy) class better?
I was thinking that I just call the Rectf Overlapping functions in game.cpp and then depending on the output I call f.ex. DamageCharacter (or whatever it's called).

Thanks again for helping out (the framework is awesome)!

Edit: Two more questions!
Im currently making my own RectF class, should I do the same thing as chili (float left, right, top, bottom) or is (float left, top, width, height) preferable?
Also, should I use RectF for my characters, or is again a Vec2 and width & height preferable?

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Attack on the Forest

Post by albinopapa » February 20th, 2018, 4:09 pm

Oh, crap, I haven't looked at the framework extensions in a while, I'll get back to you on that. I need to review how it's setup.

Regarding collision detection:
This kind of deals with software architecture and design. Think of it this way, you are wanting to check collision between different objects and deal damage against player or enemies and prevent objects from moving through each other when they are not passable. This would probably be handled in a physics component. This component wouldn't handle damage of course, but would resolve collisions. As far as calling those types of functions, you'd probably want to call those from Game.cpp after determining and resolving a collision.

Something I've done in the past is each object that is collidable had a DoCollision or HandleCollision function. Once I determined and resolved the collision, I'd pass object B to object A's collision function and object A to object B's collision function. If A needs to take damage, A would call B's GetDamageAmount() and same for B.

Code: Select all

// In Game::UpdateModel
// ... update positions
// Check, resolve and handle collisions
for( int i = 0; i < numObjects; ++i )
{
     auto& obj_a = objects[i];
     auto& obj_b = objects[i+1];
     if( phys.IsColliding( obj_a, obj_b )
     {
          obj_a.HandleCollision( obj_b );
          obj_b.HandleCollision( obj_a );
     }
}

void Wall::HandleCollision( const Object& Other )
{
     // Nothing to do here, wall doesn't take damage
}
void User::HandleCollision( const Object& Other )
{
     const auto other_type = Other.GetType();
     if( other_type == Object::Type::Enemy ||
         other_type == Object::Type::Projectile )
     {
          if( other_type == Object::Type::Projectile &&
               Other.GetOwner() != Object::Owner::User )
          {
               health -= Other.GetDamageAmount();
          }
     }
}
void Enemy::HandleCollision( const Object& Other )
{
     const auto other_type = Other.GetType();
     if( other_type == Object::Type::User ||
         other_type == Object::Type::Projectile )
     {
          if( other_type == Object::Type::Projectile &&
               Other.GetOwner() != Object::Owner::Enemy )
          {
               health -= Other.GetDamageAmount();
          }
     }
}
This code example deals with inheritance, if you haven't gotten that far, then you will have to come up with another solution.

Regarding the RectF class:
Personally, using left,top,right,bottom is a lot easier to reason about and in some cases require less math operations like trying to determine collisions and/or bounds checking. On the other hand, translating a rect that only stores it's position and size is easier because you only have to update it's position X and Y values while storing each side requires updating translating four variables. So for instance, let's say you define a collision rect as position an size first.

Easiest way is defining the rect in terms of an offset from the character as opposed to the character's position and size.
Given that the character is 32x64 pixels and it's base is at it's feet, you might store the rect as:
rect.pos.x = -16.f;
rect.pos.y = -64.f;
rect.size.width = 32.f;
rect.size.height = 64.f;

You'd then translate the rect to the players position before doing collision checking:

Code: Select all

player.pos.x = 320;
player.pos.y = 200;
RectF RectF::Translate( const Vec2f& Delta )const
{
     return pos + Delta; // -16.f + 320 = 304.f, -64.f + 200 = 136.f
}
This means that the returned collision rect's left,top corner would be ( 304.f, 136.f ). The right,bottom corner would be calculated by adding width and height to those coordinates ( 336.f, 200.f ). This assumes you want the position of the player to be centered along the X axis and at the bottom of the Y axis of the object. You'll have to change it if you want the rect to be calculated differently.

If you do the same using left,top,right,bottom:

Code: Select all

rect.left = -16.f;
rect.top = -64;
rect.right = 16.f
rect.bottom = 0;

RectF RectF::Translate( const Vec2& Delta );
{
     RectF result;
     result.left = left + Delta.x;           // -16.f + 320 = 304.f;
     result.top = top + Delta.y;           // -64.f + 200 = 136.f;
     result.right = right + Delta.x;       //  16.f + 320 = 336.f;
     result.bottom = bottom + Delta.y //    0.f + 200 = 200.f;
     
     return result;
}
Now compare the overlapping test:

Code: Select all

bool RectF::IsOverlapping( const RectF& Other )const
{
     // Stored position and size
     return 
          pos.x + size.width > Other.pos.x && pos.x < Other.pos.x + Other.size.width &&
          pos.y + size.height > Other.pos.y && pos.y < Other.pos.y + Other.size.height;

     // Stored boundaries
     return
          right > Other.left && left < Other.right &&
          bottom > Other.top && top < Other.bottom;
}
As you can see, each has it's benefits and drawbacks to readability and maybe efficiency. You can make the pos/size version of the overlapping function easier to read by having functions that return the sides after calculation GetLeft() > Other.GetRight() && GetRight() < Other.GetLeft() and so on, but the extra calculations are still there, just hidden.
Also, should I use RectF for my characters, or is again a Vec2 and width & height preferable?
No hesitation, use a Rect class, it gives you an abstraction that can be reasoned about when dealing with the object's boundaries for collision and drawing. Plus, if you are using my framework extensions for chili's framework, then you would need to create rects from the size and position for each object before drawing them anyway. Of course, you can always just write your own stuff :);
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

User avatar
Zedtho
Posts: 189
Joined: February 14th, 2017, 7:32 pm

Re: Attack on the Forest

Post by Zedtho » February 20th, 2018, 5:18 pm

Thanks a lot! That's really helpful! I'll think a bit about the rect thing then.

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Attack on the Forest

Post by albinopapa » February 20th, 2018, 11:54 pm

Ok, so assuming you have the latest version of my fork of chili's framework, the one with my additions, this is how it works. The Sprite classes are setup in a way that allows you to have offscreen sprites. If they are completely off screen, then the function exits without writing anything to screen. If the sprite is partially on screen, then it only draws what is on screen from any side of the screen/window.

I wanted to make some changes after watching how chili handled the different types of sprites, it is a little bit more elegant than using inheritance. Perhaps I will, I'm getting worn out on my current endeavors, so taking a break from it sounds good. I still never got my particle stuff working how I wanted either. The particle system works, but is very inflexible, so I'll have to work on that as well.

Bottom line, just spawn an enemy where ever you want and the framework should take care of the rest. I don't remember if that applies to the earlier versions of the framework with my changes.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

User avatar
Zedtho
Posts: 189
Joined: February 14th, 2017, 7:32 pm

Re: Attack on the Forest

Post by Zedtho » February 21st, 2018, 1:06 pm

I think I can use Destrect() and Sourcerect() for that, it doesn't do it automatically (I have a mp4 file showing that but can't send it here)

Actually, I might have one of the earlier frameworks then

Would you know how I can update it? Should I just steal the files from your framework (not files like game.h obv, more like graphics.h or similar) and replace the ones in my solution?

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Attack on the Forest

Post by albinopapa » February 21st, 2018, 3:37 pm

You can go to the github page and click on "Clone or Download" then "Download Zip".

You could also just use Visual Studio's built in git interface. If your game files were created in the same repo and branch as the framework then you might just download the zip file and extract the files you want.

I probably should have left out Game.h/.cpp from the repo.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

User avatar
Zedtho
Posts: 189
Joined: February 14th, 2017, 7:32 pm

Re: Attack on the Forest

Post by Zedtho » February 28th, 2018, 2:31 pm

I'll do that if I find some time, thanks for answering!

I've recently been trying to get a state machine working (like is shown in gameprogrammingpatterns.com ) but it really hates the inheritance I've got going on.
https://github.com/Zedtho/Attack-on-The ... ee/Sprites

Does anyone understand what the problem is?

Post Reply