GLut in C - Collision isn't working all the time - c

I'm currently working on a side scroller, my player can shoot, as do the enemies. If I hit an enemy,it should disappear. Unfortunately, it doesn't work all the time. Sometime it does, sometime not. Sometimes, it work perfectly like here :
Ennemi 30 =eX:37 - eY:51
Shot 12=sX:37 - sY:52
====
BOUM
and for some reasons, it happens that my shot go trough the enemy like it doesn't exist.
Here's how I detect collision :
void checkCollisionShot(ListShot* list,ListEnnemy* listE){
if (list == NULL || listE == NULL){
exit(EXIT_FAILURE);
}
Shot *getSh=list->first;
Ennemy *getEn=listE->first;
if (list->first!= NULL && listE->first!=NULL)
{
int i,j;
for(i=0;i<list->nbr;i++){
int sX=getSh->obj.posi.x;
int sY=getSh->obj.posi.y;
for(j=0;i<listE->nbr;i++){
int eX=getEn->obj.posi.x;
int eY=getEn->obj.posi.y;
if(getEn->obj.friend!=getSh->obj.friend){
if(sX<eX+3 && sX>=eX){
if(sY<eY+3 && sY>=eY){
printf("Boum\n");
deleteEnnemy(listE,eX,eY);
deleteShot(list,sX,sY);
}
}
}
getEn=getEn->next;
}
getSh=getSh->next;
}
}
}
I'm working with simple linked list : One for the shots, another one for the enemies. I'm browsing each element, one by one, and compare each element from a list with the position of the other list.
Is the mistake coming from this function, or does it come from one of the GLut function (-like- the refresh function) ?

Okay, I found it ! The declaration of getEn should be reset with every loop. The code look like this now :
void checkCollisionShot(ListShot* list,ListEnnemy* listE){
if (list == NULL || listE == NULL)
{
exit(EXIT_FAILURE);
}
Shot *getSh=list->first;
//GETEN IS NOT HERE ANYMORE<-----------------------------
if (list->first!= NULL && listE->first!=NULL)
{
while(getSh!=NULL){
int sX=getSh->obj.posi.x;
int sY=getSh->obj.posi.y;
Ennemy *getEn=listE->first;//<------------------THE DIFFERENCE IS HERE
while(getEn!=NULL){
int eX=getEn->obj.posi.x;
int eY=getEn->obj.posi.y;
if(getEn->obj.friend!=getSh->obj.friend){
if(sX<eX+3 && sX>=eX){
if(sY<eY+3 && sY>=eY){
//exit(0);
printf("\n\nBOUM\n");
deleteEnnemy(listE,eX,eY);
deleteShot(list,sX,sY);
break;
}
}
}
getEn=getEn->next;
}
getSh=getSh->next;
}
}
}
For the record, only the first element of the ListShot was compared with every element of the ListEnnemy. Now, every object is compared with each other.

Related

How to free all memory blocks of a picture using quadree structure with different cases?

Few weeks ago, I was trying to implement a function to display a quadtree. My current problem is concerning the same work, so I pass you this link for all the context: How to display composed quadtrees using C language?
(I'm using a few features that come from this post)
the quadtree structure:
typedef struct block_image
{
int allBlack; //boolean
struct block_image * son[4];
}block_image;
typedef block_image *image;
Currently, I’m working on a function to free all memory blocks of a quadtree. For example, if a quadtree is white, there is nothing to do because the pointer to the structure is already NULL. If a quadtree is black, we free the pointer and set it to NULL. Else, if it is a composed picture, we take care of freeing the space of the different sons.
summary: returns all blocks of an image to the memory.
My current program:
void freeMemory(image myImage)
{
if(myImage == NULL)
{
return;
}
else if(myImage->allBlack)
{
free(myImage);
myImage = NULL;
}
else
{
freeMemory(myImage->son[0]);
freeMemory(myImage->son[1]);
freeMemory(myImage->son[2]);
freeMemory(myImage->son[3]);
}
}
However, I am not sure how to check my function.
For exemple, I decided to create a white quadree and a black quadtree. But when I used freeMemory fonction and normalDisplay to see the representation of the two quadrees before and after, there was no difference.
printf("\nfreeMemory\n\n");
image white = Build_white();
image black = Build_black();
printf("before\n");
normalDisplay(black);
printf("\n");
printf("after\n");
freeMemory(black);
normalDisplay(black);
printf("\n");
printf("before\n");
normalDisplay(white);
printf("\nafter\n");
freeMemory(white);
normalDisplay(white);
printf("\n");
The result:
As you can see, there was no difference between display before and after memory.
And this is the simplest case, after that it should also work with composed images,e.g.
N +BBNB B +N+NNB+NBNNBN.
Someone advised me to use valgrind, telling me that for my program to work, there must be as many malloc() as free(). But I don't really know how to interpret the results (and if it is really useful).
the result (My variable names was not in english so, affichageNormal == normalDisplay, Rendmemoire == freeMemory and Construit_noir == Build_black)
P.S. I also have two function isWhite and isBlack to tell if a picture is black (no white elements) or white (no black element):
int isWhite(image myImage)
{
if(myImage == NULL)
{
return 1;
}
else if(myImage->allBlack)
{
return 0;
}
else if(isWhite(myImage->son[0]) && isWhite(myImage->son[1]) && isWhite(myImage->son[2]) && isWhite(myImage->son[3]))
{
return 1;
}
return 0;
}
int isblack(image myImage)
{
if(myImage == NULL)
{
return 0;
}
else if(myImage->allBlack)
{
return 1;
}
else if(isBlack(myImage->son[0]) && isBlack(myImage->son[1]) && isBlack(myImage->son[2]) && isBlack(myImage->son[3]))
{
return 1;
}
return 0;
}
It may be useful for the function.
Edit:
In case of doubt I also add the code of normalDisplay :
void normalDisplay(image myImage)
{
if(myImage == NULL)
{
printf("B");
}
else if(myImage->allBlack)
{
printf("N");
}
else
{
printf("+");
normalDisplay(myImage->son[0]);
normalDispay(myImage->son[1]);
normalDisplay(myImage->son[2]);
normalDisplay(myImage->son[3]);
}
}
A robust way to free the memory from the quadtree is to make sure you feedback that a pointer no longer is pointing to valid memory. Since your current freeMemory only takes an block_image pointer, the function cannot convey this information back to the caller.
Better would be to change its interface to provide this facitily with another level of indirection.
void freeMemory(image *myImage) {
if (myImage != NULL && *myImage != NULL) {
int sonSize = sizeof((*myImage)->son) / sizeof((*myImage)->son[0]);
while (sonSize) freeMemory(&(*myImage)->son[--sonSize]);
free(*myImage);
*myImage = NULL;
}
}
On a side note, your original freeMemory does have a memory leak, but hoping you can figure that out.
This way, *myImage = NULL will convey this change to the caller. On the calling side it would look something like this:
puts("\nfreeMemory\n");
image white = Build_white();
image black = Build_black();
puts("before");
normalDisplay(black);
puts("");
puts("after");
freeMemory(&black);
normalDisplay(black);
puts("");
puts("before");
normalDisplay(white);
puts("\nafter");
freeMemory(&white);
normalDisplay(white);
puts("");
With this your normalDisplay will better provide you with an "image" of the situation.

C - Linked List Segmentation Fault During Display

Edit 2: I realized that I did not have a "Not found" result for any query not in the database. Changes have been made to introduce this feature. Here is the current test and test output:
Input:
3
sam
99912222
tom
11122222
harry
12299933
sam
edward
harry
Output:
Not found
=0
Not found
=0
Not found
=0
Not found
=0
sam
=99912222
Not found
=0
Not found
=0
Not found
[Infinite loop continues]
Edit: I have changed a few things in the while loop in display(). I am now getting an infinite loop printing "=0" except for the third or fourth cycle through the search. Hmmm...
By the way, thanks for the reminder of testing strings with ==. Seems like a no-brainer now.
I have done some searching and have yet to be able to understand where I have gone wrong with my code. I am working on a challenge which will result in a simple phone-book program. It will take input of a number (the number of entries to be added) then the names and associated phone numbers (no dashes or periods). After the entries have been added then the user can search for entries by name and have the number displayed in the format "name=number".
The code throws a segmentation fault with the while loop in the display() function. I assume that I am attempting to print something assigned as NULL, but I cannot figure out where I have gone wrong. Any help would be very appreciated.
Lastly, the challenge calls for me to read queries until EOF; however, this confuses me since I am to accept user input from stdin. What does EOF look like with stdin, just a register return (\n)?
(PS: This is my first attempt at linked lists, so any pointers would be greatly appreciated.)
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
void add_entry(void);
void display(void);
struct phonebook {
char name[50];
int number;
struct phonebook *next;
};
struct phonebook *firstp, *currentp, *newp;
char tempname[50];
int main() {
int N;
firstp = NULL;
scanf("%d", &N);
for (int i = 0; i < N; i++) {
add_entry();
}
display();
return 0;
}
void add_entry(void) {
newp = (struct phonebook*)malloc(sizeof(struct phonebook));
if (firstp == NULL) firstp = currentp = newp;
else {
currentp = firstp;
while (currentp->next != NULL)
currentp = currentp->next;
currentp->next = newp;
currentp = newp;
}
fgets(currentp->name, 50, stdin);
scanf("%d", &currentp->number);
currentp->next = NULL;
}
void display(void) {
while (strcmp(tempname, "\n") != 0) {
currentp = firstp;
fgets(tempname, 50, stdin);
while (strcmp(currentp->name, tempname) != 0) {
if (currentp->next == NULL) {
printf("Not found\n");
break;
}
currentp = currentp->next;
}
printf("%s=%d\n", currentp->name, currentp->number);
}
}
Your problem is that you never find the entry you're looking for. The expression currentp->name != tempname will always be true, since those are always unequal. In C, this equality test will not compile into a character-by-character comparison, but into a comparison of pointers to currentp->name and tempname. Since those are never at the same addresses, they will never be equal.
Try !strcmp(currentp->name, tempname) instead.
The reason you crash, then, is because you reach the end of the list, so that currentp will be NULL after your loop, and then you try to print NULL->name and NULL->number, actually causing the crash.
Also, on another note, you may want to start using local variables instead of using global variables for everything.
Not sure if this solves the problem, but you can't directly compare strings with != in C. You need to use if( strcmp( string1, string2 ) == 0 ) to check.
fgets doesn't take EOF (= -1) like getchar does, but it does include '\n' and pad the rest with NULL (= 0) so checking for EOF is not really helpful, but yes you can stop after \n or NULL.

A doubly linked list

I wrote a program to manage Bank accounts by the means of a doubly linked list, but I found a problem with the cancellation procedure.
void suppCompte (int numCpt) {
CompteBancaire *pnt = first;
if (first==NULL) {
printf("la liste vide !\n");
}else{
while (pnt != NULL && pnt->idf.numCompte != numCpt) {
pnt=pnt->next;
if (pnt==first) { // Remove the first node
first=pnt->next;
free(pnt);
}else if (pnt->next==NULL) { // Remove the last node
pnt->prc->next=NULL;
free(pnt);
}else{ // Remove a moddle node
pnt->prc->next=pnt->next; // <==== !!!!
pnt->next->prc=pnt->prc; // <==== !!!!
free(pnt);
}
}
}
}
I still have the same problem, even if I tried to do this method:
-(pnt->prc)->next=pnt->next;
The line after the while loop causes the problem, i.e. pnt=pnt->next should be after the if-else if . So if there is only 1 node, then pnt will be NULL, which causes problem in the else part. The modified code is :
void suppCompte (int numCpt)
{
CompteBancaire *pnt=first;
if (first==NULL)
printf("la liste vide !\n");
else
{
while (pnt!=NULL && pnt->idf.numCompte!=numCpt)
CompteBancaire *temp=pnt;
if (pnt==first) // Remove the first node
{ first=pnt->next;
}
else if (pnt->next==NULL) // Remove the last node
{ pnt->prc->next=NULL;
}
else // Remove a moddle node
{ pnt->prc->next=pnt->next; <==== !!!!
pnt->next->prc=pnt->prc; <==== !!!!
}
pnt=temp->next;
free(temp);
}
}
Check your pointers to make sure that they are not NULL. This can be done with two easy if loops. You always have to watch out for this sort of thing with doubly linked lists, and you have to think carefully about the order of your instructions.
Then, after you set the pointers to sort of "point around" the current node, set the pointers of the current node to NULL.
Also, consider using gdb. It is the Gnu DeBugger. If you compile with gcc, you can say gcc -g <files and other stuff> to compile with gdb debugging symbols. Then you can run the program in gdb, and inspect the values of variables, watch stuff evaluate, etc. You can probably find a lot of good material on this.

Issues with repeated key checking with getch()

I am having issues with repeating key checking using a function that utilizes getch().
Here is a code example:
static char g_keybuffer[256];
_Bool IsKeyDown(char c)
{
char ch;
if(kbhit())
ch = getch();
if(ch == -32 || ch == 224)
{
ch = getch();
}
g_keybuffer[ch] = 1;
if(g_keybuffer[c] == 1)
{
g_keybuffer[c] = 0;
return 1;
}
return 0;
}
/*
*
*/
int main(int argc, char** argv) {
while(1)
{
if(IsKeyDown('a'))
{
printf("Test\n");
}
if(IsKeyDown('a'))
{
printf("Hello\n");
}
else if(IsKeyDown('b'))
{
printf("World\n");
}
Sleep(100);
}
return (EXIT_SUCCESS);
}
I know why the problem occurs. When a key is pressed, kbhit is true once per loop, and sets ch to the character retrieved from the buffer. When IsKeyDown is used, if it is equal to the parameter, the key in the buffer g_keybuffer is set equal to zero to avoid having a key be "down" infinitely. The problem with this is if you want to check if the same key is down more than once, only the first instance of IsKeyDown will be ran, with the rest being invalid due to the g_keybuffer of the key now being 0.
Does anyone know how I can change IsKeyDown to give it the ability to check the same key multiple times per looping? I'm stuck.
Your problem is because you are setting g_keybuffer[c] to 0 after you get a hit for the key state. I'm guessing you have done this to avoid getting the same result twice - but that is just a workaround. The only way to do what you want to do properly is to choose a library that is actually made to capture the keyboard state.
Most graphics libraries have functions for capturing keyboard states. I don't know of any solutions thought that don't involve a little overhead if you are just writing a small program.

Having trouble deleting elements in doubly linked list

I've been trying for about 5 hours to get this code to work properly, and the code is written based on hours of internet research.
I have modified it several times, all of which gave me segmentation faults, so this is the only version that runs.
What is happening, is that the code is cycling through, and deleting not only the element you want to get rid of, but all elements preceding it. So, if you want to delete the last element, everything in the list goes. Or, if you wanted to delete the second element, the first and second go, and so on.
It thinks that every name entered is the top name for some reason.
static void menu_delete_employee(void)
{
char deletename[MAX_NAME_LENGTH+1];
char namecheck[MAX_NAME_LENGTH+1];
int errorcheck = 0;
int foundit = 0;
fprintf(stderr, "Enter the name of the employee you wish to delete\n");
gets(deletename);
employee_list = top;
employee_list->name;
do
{
strcpy (namecheck, employee_list->name);
printf("namecheck = %s\n", namecheck);
errorcheck = (strcmp (namecheck, deletename));
printf("errorcheck = %i\n", errorcheck);
switch (errorcheck)
{
case 0:
{
printf("This is the right name\n");
foundit = 1;
if (employee_list->prev == NULL)
{
printf("top name\n");
top = employee_list->next;
}
else
{
if (employee_list->next == NULL)
{
printf("last one\n");
temp = employee_list->prev;
temp-> next = NULL;
free (employee_list);
}
else
{
printf("somewhere in the middle");
temp = employee_list->prev;
temp->next = employee_list->next;
employee_list->next->prev = temp;
free (employee_list);
}
}
printf("delete successful\n");
break;
}
default:
{
printf("not this one\n");
errorcheck = 0;
employee_list = employee_list->next;
break;
}
}
}
while (foundit == 0);
if (foundit == 0)
printf("Name not recognised\n.");
return;
}
Any help would be much appreciated.
Maybe the doubly-linked list is not built up the way you think it should. This has to be checked first.
Assuming the topology is correct, there are still a couple of issues with this code:
employee_list->name; (just above the do loop): what is this?
strcpy (namecheck, employee_list->name); : you do not need to copy, this is just a shorthand, so namecheck could be a (const) string pointer.
switch (errorcheck) : this has only 2 arms, why don't you use an if ?
if (employee_list->prev == NULL) ...: you just move the top pointer here but do not delete the top item, this will cause memory leaks. You also do not set the prev pointer of the next-to-top item to NULL.
In the "somewhere in the middle" part: you free employee_list which is the current position pointer. The next item to be processed should be temp->next, right? This is probably your problem because you do not take care of moving the current pointer along. Moreover, it is much better to set a pointer explicitly called tobedeleted to the item to be deleted, make sure the pointer used to iterate along the list (employee_list in your case) is moved appropriately, and when *tobedeleted is appropriately isolated out from the doubly linked list then issue the free(tobedeleted) command.
employee_list = employee_list->next; : you should check for employee_list turning into NULL at the last item, and exit the loop. Otherwise Bad Things will happen.
Final advice: you really need to consult a good C book... Kernighan and Ritchie
for instance. Way better than "Internet research".

Resources