This page was last updated on March 13th, 2020(UTC) and it is currently May 30th, 2023(UTC).
That means this page is 3 years, 78 days, 3 hours, 21 minutes and 18 seconds old. Please keep that in mind.
44 - Object Collision
First and foremost, vtools.S needed updated with a function an a typofix.
.global ___cxa_pure_virtual
.text
/************************************************************************\
| int __cxa_pure_virtual() |
\************************************************************************/
___cxa_pure_virtual: int3
/************************************************************************\
| int easymode() |
\************************************************************************/
_easymode:
The issue is that since some DOS emulators (including the one I'm using) refuse to support long filenames, libstdc++ cannot be linked, because it's too long. We could go ahead and modify all the files so they fit within the character limit of DOS, but that would be a pain for me to do, and it would miss an opportunity to teach you how to get around such issues. In this case, __cxa_pure_virtual() and a few other functions were missing. Firstly, __cxa_pure_virtual(), according to what I found, is actually just a function that should either crash, go into an infinite loop, or something to tell the user that the program is horribly broken. Unfortunately, it can happen that somehow the compiler doesn't catch an impossible scenario like where a virtual function is called in a constructor (those typeless functions named after the class), which should never happen. So, all we did is throw out int3, which causes the program to crash with a breakpoint exception. Secondly, I forgot to fix main() to easymode() when I set this up earlier. It's a minor typo, and it's in a comment, so you don't actually have to fix it, but you should anyway when you catch this type of error (instead of fixing it in previous lessions, I decided to leave it here to show you the kinds of things to watch out before making a final release, which I failed to do).
Next, you'll want to add "-fno-rtti" which takes care of the other functions not being linked. Apparently these functions are used for scenarios that are not necessarily impossible, but not necessarily common, either. You won't normally need to drop this into a makefile, but we will for DOS for now. Next, we need to add the following two lines to our settings header:
extern "C" double sqrt(double x);
extern "C" int abs(int j);
We'll ultimately need them for some of our math. You could also add them to specific .CPP files if you needed to, but that's your choice. In the end, it really doesn't matter much which, but putting them in settings could be easier. You could also roll your own abs() function, too if you needed. I recommend not trying to roll your own sqrt() function unless you're doing it in assembly (since x86 has fsqrt as an instruction).
Next, we redefine "tester" to be "collidable", and we define a "bullet" to be collidable as well. We can then add the following code to the draw() function that we had from before:
tester.draw();
bullet.draw();
bullet.check_coll(tester);
Then we have the following files, which I hope you can guess the names, and don't forget to include the header in main.
#ifndef _COLLIDABLE_H
#include "DRAWABLE.H"
class collidable: public drawable {
public:
int dmg, rdmg;
float radius;
collidable(int x, int y);
void draw();
void check_coll(collidable &aite);
};
#endif
#define _COLLIDABLE_H true
#include "COLLIDAB.H"
#include <stdio.h>
//-------------------------------------------------------------------------
unsigned char bmp[] = {
" "
" "
" "
" "
" "
" "
" "
};
collidable::collidable(int x, int y){
bitmap = bmp;
xs = 7;
ys = 7;
radius = (xs+ys)/(float)4;
this->x = x;
this->y = y;
dmg = 0;
rdmg = 0;
}
//-------------------------------------------------------------------------
void collidable::draw(){ emplace(); }
//-------------------------------------------------------------------------
void collidable::check_coll(collidable aite){
int xdiff = abs(x-aite.x);
int ydiff = abs(y-aite.y);
if(sqrt((xdiff * xdiff) + (ydiff * ydiff)) <= (radius + aite.radius))
printf("I touched something!\n");
printf("%f %f\n", sqrt((xdiff * xdiff) + (ydiff * ydiff)), (radius + aite.radius));
}
//-------------------------------------------------------------------------
And, once again, we have another dirty testing function. When you're done playing around, we have a bit of code to remove. I'm also sure you noticed the screen is really jittery, but that's just the result of text mode and graphics mode not exactly being all that compatible. Now, something to note. The FPU (Floating Point Unit) code is slower, but I'm choosing to use it anyawy, because, while we could define xradius and yradius and skip the sqrt, I plan on using roudner shapes, and using sqrt with a rounder bullet is more accurate, especially if we're going to have bullets that go at angles other than 90-degree angles. Below is the cleaned up version of the code that we're going to use for the next lesson after you're done playing around. Also, the (float) if you haven't figured it out yet is to force the calculation for radius to be floating point, which it won't reliably be otherwise.
#include "COLLIDAB.H"
//-------------------------------------------------------------------------
collidable::collidable(int x, int y){
this->x = x;
this->y = y;
dmg = 0;
rdmg = 0;
}
//-------------------------------------------------------------------------
void collidable::check_coll(collidable aite){
int xdiff = abs(x-aite.x);
int ydiff = abs(y-aite.y);
if(sqrt((xdiff * xdiff) + (ydiff * ydiff)) <= (radius + aite.radius))
aite.rdmg = dmg;
}
//-------------------------------------------------------------------------
And also draw will become virtual and be set to equal 0, because we need to force the next child to define it. The purpose of this class being different from drawable was simply so we wouldn't necessarily need all the extra bells and whistles if we later wanted to add background objects or something other than stars. I don't actually plan on doing it, but you may. You should also notice that we've "inherited" things from the second class mentioned after the colon in our class definition. I plan on doing this again, but this time, once for a "player ship", then an "enemy ship" and also "bullets" which we will have shared between player and enemy for the time being.
Get your own web kitty here!
©Copyright 2010-2023. All rights reserved.