Donc je travaille sur un jeu pour mon cours de science informatique en utilisant Dev-C++ 5.11 et Allegro 4.2, j'arrive à la fin du projet et je veux enfin régler un problème que j'ai eu pendant un certain temps maintenant. Mon code est assez long pour utiliser un seul fichier .cpp, mais quand j'essaie de placer mes fonctions dans un fichier séparé, je reçois une série de "définitions multiples" des erreurs "définies ici". J'ai regardé en ligne et la plupart des gens qui ont ce problème ont inclus leur fichier. Cpp dans leur principal ou quelque chose d'équivalent, mais je n'ai pas fait cela et ne peux pas comprendre pourquoi cela ne fonctionnera pas. Les erreurs pointent vers toutes les variables que je déclare dans l'en-tête (les bitmaps ainsi que le tableau char et ints).Erreurs de définition multiple; C++ travailler avec Allegro
Fichiers:
asteroidsMain.cpp
functions.cpp
asteroids.h
J'utilise également un fichier de données.
Fichier principal:
#include <allegro.h>
#include <alfont.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "asteroids.h"
#include "asteroids_data.h"
//Creating movement timer (also used for typing)
volatile long speed_counterA = 0;
void increment_speed_counterA() {
speed_counterA++;
}
END_OF_FUNCTION(increment_speed_counterA);
//Creating laser timer
volatile long speed_counterB = 0;
void increment_speed_counterB() {
speed_counterB++;
}
END_OF_FUNCTION(increment_speed_counterB);
//Creating asteroid timer
volatile long speed_counterC = 0;
void increment_speed_counterC() {
speed_counterC++;
}
END_OF_FUNCTION(increment_speed_counterC);
int main() {
//Initializations
allegro_init();
alfont_init();
set_color_depth(desktop_color_depth());
set_gfx_mode(GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0);
install_sound(DIGI_AUTODETECT, MIDI_AUTODETECT, NULL);
install_keyboard();
install_mouse();
install_timer();
//Movement timer
LOCK_VARIABLE(speed_counterA);
LOCK_FUNCTION(increment_speed_counterA);
install_int_ex(increment_speed_counterA, BPS_TO_TIMER(60));
//Laser firing timer
LOCK_VARIABLE(speed_counterB);
LOCK_FUNCTION(increment_speed_counterB);
install_int_ex(increment_speed_counterB, BPS_TO_TIMER(60));
//Asteroid generation timer
LOCK_VARIABLE(speed_counterC);
LOCK_FUNCTION(increment_speed_counterC);
install_int_ex(increment_speed_counterC, BPS_TO_TIMER(60));
//Randomizing seed
srand(time(0));
//Creating/loading BITMAPs formain game
BITMAP *buffer = create_bitmap(800, 600);
shipStopped = loadImage("shipStopped");
shipMoving = loadImage("shipMoving");
laserSprite = loadImage("laser");
smallAsteroid = loadImage("small_Asteroid");
medAsteroid = loadImage("med_Asteroid");
largeAsteroid = loadImage("large_Asteroid");
//General use variables for screen control
int onScreen = 0, i = 0, j = 0;
bool quit = false;
//Retrieving and sorting scores
numOfScores = getHighs(name, score);
sortHighs(name, score);
//Loads main screen
onScreen = changeScreen(0);
while (!quit) {
//If there was an issue loading datafile, error is returned
if (onScreen == -1) {
return 1;
}
else if (onScreen == 0) {
while (onScreen == 0) {
//Primary check is for quitting program, other buttons lead to separate screens
if ((mouse_b & 1) && mouse_x > 400 - 75 &&
mouse_x < 400 + 75 && mouse_y > 450 && mouse_y < 4505 + quitButton->h) { //For clicking Quit
quit = true;
onScreen = -2;
}
else if ((mouse_b & 1) && mouse_x > 400 - 75 &&
mouse_x < 400 + 75 && mouse_y > 150 && mouse_y < 150 + playButton->h) { //For clicking Play
onScreen = changeScreen(2);
}
else if ((mouse_b & 1) && mouse_x > 400 - 75 &&
mouse_x < 400 + 75 && mouse_y > 250 && mouse_y < 250 + highsButton->h) { //For clicking Highscores
onScreen = changeScreen(3);
}
else if((mouse_b & 1) && mouse_x > 400 - 75 &&
mouse_x < 400 + 75 && mouse_y > 350 && mouse_y < 350 + creditsButton->h) { //For clicking Credits
onScreen = changeScreen(4);
}
}
}
else if (onScreen == 2) { //Difficulty choice screen
if ((mouse_b & 1) && mouse_x > 600 - (playButton->w/2) &&
mouse_x < 600 + (playButton->w/2) && mouse_y > 192 && mouse_y < 192 + playButton->h) {
onScreen = changeScreen(1);
}
else if ((mouse_b & 1) && mouse_x > 635 && mouse_x < 775 &&
mouse_y > 575 - menuButton->h && mouse_y < 575) { //Returns to main menu
onScreen = changeScreen(0);
}
}
else if (onScreen == 3) { //Highscore screen
if ((mouse_b & 1) && mouse_x > 635 && mouse_x < 775 &&
mouse_y > 575 - menuButton->h && mouse_y < 575) { //Returns to main menu
onScreen = changeScreen(0);
}
}
else if (onScreen == 4) { //Credit screen
if ((mouse_b & 1) && mouse_x > 635 && mouse_x < 775 &&
mouse_y > 575 - menuButton->h && mouse_y < 575) { //Returns to main menu
onScreen = changeScreen(0);
}
}
else if (onScreen == 51) { //Game over screen
if (points <= score[9]) {
if ((mouse_b & 1) && mouse_x > 25 && mouse_x < 175 &&
mouse_y > 575 - menuButton->h && mouse_y < 575) { //Begins a new game
onScreen = changeScreen(2);
}
else if ((mouse_b & 1) && mouse_x > 635 && mouse_x < 775 &&
mouse_y > 575 - menuButton->h && mouse_y < 575) { //Returns to main menu
onScreen = changeScreen(0);
}
}
else {
if (mouse_b & 1) {
//Adding new highschore to array
score[9] = points;
strcpy(name[9], "");
if (numOfScores < 10) {
numOfScores++;
}
onScreen = changeScreen(52);
}
}
}
else if (onScreen == 52) {
speed_counterA = 0;
int keyEnt = 0, len = 0;
char keyHold;
//Text entering for highscore name, moves to next screen on enter
while (!key[KEY_ENTER]) {
//Preventing multiple printing of same key
while (keypressed() && speed_counterA % 3 == 0) {
//Reading key from keyboard and making it useable
keyEnt = readkey();
keyHold = keyEnt & 0xff;
if (keyHold >= 32 && keyHold <= 126) { //Adding chars to name string
len = strlen(name[9]);
if (len < 19) { //Restricting the number of characters you can enter, beyond this does not save properly
name[9][len] = keyHold;
name[9][len + 1] = '\0';
}
}
else if (key[KEY_BACKSPACE]) { //Deleting if backspace char is pressed
name[9][len] = '\0';
len--;
}
clear_keybuf();
}
//Printing text
textprintf_centre_ex(buffer, font, 400, 300, WHITE, -1, "What is your name: %s", name[9]);
textprintf_centre_ex(buffer, font, 400, 500, WHITE, -1, "** press enter to conitue **");
// Blit the buffer
blit(buffer, screen, 0, 0, 0, 0, 800, 600);
clear(buffer);
}
onScreen = changeScreen(53);
}
else if (onScreen == 53) {
if ((mouse_b & 1) && mouse_x > 25 && mouse_x < 175 &&
mouse_y > 575 - menuButton->h && mouse_y < 575) { //Begins a new game
onScreen = changeScreen(2);
}
else if ((mouse_b & 1) && mouse_x > 635 && mouse_x < 775 &&
mouse_y > 575 - menuButton->h && mouse_y < 575) { //Returns to main menu
onScreen = changeScreen(0);
}
}
else if (onScreen == 1) { //Game screen
//Defining
Laser laser[50];
Asteroid asteroid[10];
//Initializing lasers and asteroids
for (i = 0; i < 50; i++) {
laser[i].pos.x = 0;
laser[i].pos.y = 0;
laser[i].angle = 0;
laser[i].onScreen = false;
}
for (i = 0; i < 10; i++) {
asteroid[i].pos.x = 0;
asteroid[i].pos.y = 0;
asteroid[i].angle = 0;
asteroid[i].onScreen = false;
}
//Game specific variables, reset for every new game
int move = 0, lasers= 0, asteroids = 0;
float angle = 0;
bool collide = false;
points = 0;
//Spawning ship when game screen loads
Coordinate ship;
ship.x = 400 - (shipStopped->w/2);
ship.y = 300 - (shipStopped->h/2);
//Reseting game timers
speed_counterA = 0;
speed_counterB = 0;
speed_counterC = 0;
while (onScreen == 1) { //Game screen
while (speed_counterA > 0) {
//Ship movement
if (key[KEY_UP] && key[KEY_RIGHT]){
ship.y -= 3;
ship.x += 3;
angle = 32;
}
else if (key[KEY_UP] && key[KEY_LEFT]){
ship.y -= 3;
ship.x -= 3;
angle = 224;
}
else if (key[KEY_DOWN] && key[KEY_RIGHT]) {
ship.y += 3;
ship.x += 3;
angle = 96;
}
else if (key[KEY_DOWN] && key[KEY_LEFT]) {
ship.y += 3;
ship.x -= 3;
angle = 160;
}
else if (key[KEY_UP]){
ship.y -= 6;
angle = 0;
}
else if (key[KEY_RIGHT]) {
ship.x += 6;
angle = 64;
}
else if (key[KEY_LEFT]) {
ship.x -= 6;
angle = 192;
}
else if (key[KEY_DOWN]) {
ship.y += 6;
angle = 128;
}
//Laser movement
for (i = 0; i < 50; i++) {
laser[i] = moveLaser(laser[i]);
}
//Asteroid movement
for (i = 0; i < 10; i++) {
asteroid[i] = moveAsteroid(asteroid[i]);
}
speed_counterA--;
}
//Key trigger for laser firing, if is first as having timer first
//would cause many hits not to be properly registered especially if
//tapping too fast, this allows firing at will with a fastest firing of every 0.15s
if (key[KEY_SPACE]) {
//Laser firing timer
while (speed_counterB > 9) {
//Laser shooting
laser[lasers] = fireLaser(angle, ship.x, ship.y);
if (lasers >= 49) {
lasers = 0;
}
lasers++;
speed_counterB -= 10;
}
}
//Asteroid spawning counter
while (speed_counterC > 59) { //Spawns an asteroiud every second
//Keeping asteroids within array range
if (asteroids >= 9){
asteroids = 0;
}
//Generating asteroid
asteroid[asteroids] = genAsteroid(1, -1);
asteroids++;
speed_counterC -= 60;
}
//If ship goes out top, it comes in bottom; vice versa
if (ship.y <= 0 - ((shipStopped->h/2))) {
ship.y += (600);
}
else if (ship.y >= 600 - ((shipStopped->h/2))) {
ship.y -= (600);
}
//If ship goes out left, it comes in right; vice versa
if (ship.x <= 0 - ((shipStopped->w/2))) {
ship.x += (800);
}
else if (ship.x >= 800 - ((shipStopped->w/2))) {
ship.x -= (800);
}
//Drawing lasers
for (i = 0; i < 50; i++) {
if (laser[i].onScreen) {
rotate_sprite(buffer, laserSprite, laser[i].pos.x, laser[i].pos.y, ftofix(laser[i].angle));
}
}
//Drawing ship
if (key[KEY_UP] || key[KEY_DOWN] || key[KEY_LEFT] || key[KEY_RIGHT]) {
rotate_sprite(buffer, shipMoving, ship.x, ship.y, ftofix(angle)); //Ship sprite with engines firing
}
else {
rotate_sprite(buffer, shipStopped, ship.x, ship.y, ftofix(angle)); //Ship sprite no flames
}
//Drawing asteroids
for (i = 0; i < 10; i++) {
if (asteroid[i].onScreen == true) {
//Drawing sprite based on asteroid type
if (asteroid[i].type == 1) { //Large asteroid
draw_sprite(buffer, largeAsteroid, asteroid[i].pos.x, asteroid[i].pos.y);
}
else if (asteroid[i].type == 2) { //Medium asteroid
draw_sprite(buffer, medAsteroid, asteroid[i].pos.x, asteroid[i].pos.y);
}
else if (asteroid[i].type == 3) { //Small asteroid
draw_sprite(buffer, smallAsteroid, asteroid[i].pos.x, asteroid[i].pos.y);
}
}
}
//Checks bb collisions
for (i = 0; i < 50; i++) {
for (j = 0; j < 10; j++) {
if (laser[i].onScreen && asteroid[j].onScreen) {
collide = checkCollision(asteroid[j].type, 0, asteroid[j].pos, laser[i].pos);
if (collide) {
laser[i].onScreen = false;
asteroid[j].onScreen = false;
points += 100 * asteroid[j].type;
//Splitting med or large asteroids into 2 asteroids one type down
if (asteroid[j].type < 3) {
asteroid[asteroids] = splitAsteroid(1, asteroid[j]);
asteroid[j] = splitAsteroid(2, asteroid[j]);
asteroids++;
}
}
}
}
}
//Printing score
textprintf_ex(buffer, font, 10, 5, WHITE, -1, "Score: %d", points);
textprintf_ex(buffer, font, 660, 5, WHITE, -1, "Press esc to quit");
// Blit the buffer
blit(buffer, screen, 0, 0, 0, 0, 800, 600);
clear(buffer);
for (i = 0; i < 10; i++) {
if (asteroid[i].onScreen) {
collide = checkCollision(asteroid[i].type, 1, asteroid[i].pos, ship);
if (collide) {
onScreen = changeScreen(51);
}
}
}
//To leave game screen and return to main menu
if (key[KEY_ESC]) {
onScreen = changeScreen(0);
}
}
}
}
//Freeing memory
destroy_bitmap(playButton);
destroy_bitmap(highsButton);
destroy_bitmap(creditsButton);
destroy_bitmap(quitButton);
destroy_bitmap(shipStopped);
destroy_bitmap(shipMoving);
destroy_bitmap(laserSprite);
destroy_bitmap(smallAsteroid);
destroy_bitmap(medAsteroid);
destroy_bitmap(largeAsteroid);
return 0;
}
END_OF_MAIN()
fichier d'en-tête est:
#ifndef ASTEROIDS_H_
#define ASTEROIDS_H_
#define WHITE makecol(255, 255, 255)
#define BLACK makecol(0, 0, 0)
#include <allegro.h>
#include <alfont.h>
//Made global so size pointers can be used throughout
BITMAP *playButton;
BITMAP *playAgainButton;
BITMAP *highsButton;
BITMAP *creditsButton;
BITMAP *quitButton;
BITMAP *menuButton;
BITMAP *shipStopped;
BITMAP *shipMoving;
BITMAP *laserSprite;
BITMAP *smallAsteroid;
BITMAP *medAsteroid;
BITMAP *largeAsteroid;
//Highscore variables are made global; technically bad,
//but makes simplifies printing greatly
int score[10], numOfScores, points;
char name[10][20];
struct Coordinate {
int x, y;
};
struct Laser {
Coordinate pos;
float angle;
bool onScreen;
};
struct Asteroid {
Coordinate pos;
int type;
int angle;
bool onScreen;
};
int changeScreen(int toLoad);
BITMAP* loadImage(const char image[20]);
int getHighs(char name[][20], int high[]);
void sortHighs(char name[][20], int score[]);
void saveHighs(const char name[][20], const int score[], int numOfScores);
Laser fireLaser(float angle, int ship_x, int ship_y);
Laser moveLaser(Laser laser);
Asteroid genAsteroid(int difficulty, int type);
Asteroid splitAsteroid(int order, Asteroid asteroid);
Asteroid moveAsteroid(Asteroid asteroid);
bool checkCollision(int typeA, int typeB, Coordinate asteroid, Coordinate object);
#endif
Le fichier fonctions se résume à:
#include <allegro.h>
#include <alfont.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "asteroids.h"
#include "asteroids_data.h"
/*~500 lines of functions*/
Tout fonctionne quand je mets simplement les fonctions ci-dessous la principale
Copie du journal de compilation:
g++.exe -c asteroidsMain.cpp -o asteroidsMain.o -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include/c++" -I"C:/Program Files (x86)/Dev-Cpp/include" -m32
g++.exe asteroidsMain.o functions.o -o POPE_Greg_Asteroids.exe -L"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib32" -L"C:/Program Files (x86)/Dev-Cpp/lib" -lalfont -lalleg -m32
functions.o:functions.cpp:(.bss+0x0): multiple definition of `playButton'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x0): first defined here
functions.o:functions.cpp:(.bss+0x4): multiple definition of `playAgainButton'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x4): first defined here
functions.o:functions.cpp:(.bss+0x8): multiple definition of `highsButton'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x8): first defined here
functions.o:functions.cpp:(.bss+0xc): multiple definition of `creditsButton'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0xc): first defined here
functions.o:functions.cpp:(.bss+0x10): multiple definition of `quitButton'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x10): first defined here
functions.o:functions.cpp:(.bss+0x14): multiple definition of `menuButton'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x14): first defined here
functions.o:functions.cpp:(.bss+0x18): multiple definition of `shipStopped'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x18): first defined here
functions.o:functions.cpp:(.bss+0x1c): multiple definition of `shipMoving'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x1c): first defined here
functions.o:functions.cpp:(.bss+0x20): multiple definition of `laserSprite'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x20): first defined here
functions.o:functions.cpp:(.bss+0x24): multiple definition of `smallAsteroid'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x24): first defined here
functions.o:functions.cpp:(.bss+0x28): multiple definition of `medAsteroid'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x28): first defined here
functions.o:functions.cpp:(.bss+0x2c): multiple definition of `largeAsteroid'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x2c): first defined here
functions.o:functions.cpp:(.bss+0x40): multiple definition of `score'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x40): first defined here
functions.o:functions.cpp:(.bss+0x68): multiple definition of `numOfScores'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x68): first defined here
functions.o:functions.cpp:(.bss+0x6c): multiple definition of `points'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x6c): first defined here
functions.o:functions.cpp:(.bss+0x80): multiple definition of `name'
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x80): first defined here
collect2.exe: error: ld returned 1 exit status
C:\Users\Greg\Documents\Asteroids B\Makefile.win:25: recipe for target 'POPE_Greg_Asteroids.exe' failed
mingw32-make.exe: *** [POPE_Greg_Asteroids.exe] Error 1
Ce n'est pas le problème, mais les noms qui contiennent deux traits de soulignement consécutifs ('__ASTEROIDS_H_INCLUDED__') et les noms commençant par un trait de soulignement suivi d'une lettre majuscule sont réservés à l'implémentation. Ne les utilisez pas dans votre code. –
Affiche le journal de construction. Nous devons voir au moins quelques-uns des messages d'erreur exacts. Les messages indiqueront clairement où et quelles sont les multiples définitions. C'est évidemment des informations vitales pour cette question. – kaylum
"Je reçois une série de" définitions multiples "des erreurs" définies ici "- avez-vous ** lu ** les messages d'erreur? Je n'ai jamais vu un compilateur qui donne ce genre de message d'erreur sans mentionner les ** noms ** des symboles qui sont multipliés, et c'est un grand indice sur la façon de résoudre le problème. Recherchez ces noms, et supprimez ** le code qui ne les concerne pas, jusqu'à ce que vous ayez le plus petit programme possible pour montrer le problème. Vous pourriez juste voir comment le réparer vous-même. –