Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

23.04.2007, 21:52

KONSOLE: Altar of Shadows

Hi :)

manche werden es kaum glauben, aber ich hab n kleines konsolenspielchen gebastelt. es ist noch nicht fertig, aber es ist schon vorzeigbar :)

aber vorerst mal.

Worum geht es?
Es handelt sich um ein kleines RPG "Altar of Shadows". Der Spieler lenkt seinen Charakter durch verschiedene Karten. Dabei kann er verschiedene Monster besiegen, um Gold und Erfahrung zu sammeln um Gegenstände zu kaufen.

Story?
Unser Held "Arexis" startet in einer Stadt "Eralda". Es ist lange her, als er gegen böse Mächte kämpfte und seine Künste einsetzte, aber eine neue Bedrohung scheint in der Nähe der Stadt im "Turm von Aeaana" sich anzubrauen. Darum wird er vom Ältesten gebeten, sich dieser Sache zu entledigen.

Features?
- 1 Held: levelbar (derzeit unendlich)
- 4 Karten (Eralda, Fields of Outer Towers, Field of Tower Aeaana, Tower Aeanna"
- Unterschiedliche Items: vom kleinen Heiltrank, bis hin zum Langschwert oder Plattenpanzer (Itemarten: Waffe, Stiefel, Rüstung, Helm, Tränke)
- mit Lvl 3 kann sich der Held entscheiden ob er ein Kämpfer, Magier oder Kampfmagier sein will(Jede Klasse hat unterschiedliche Fähigkeiten und kann unterschiedliche Gegenstände tragen).
- 2 Haendler: Trank und Waffenhaendler
- 1 NPC : Dorfältester
- Unterschiedliche Gegner: die Gegner passen sich der Staerke des Helden an. So kämpft ihr anfangs nur bis zu maximal 3 Gegner(Ratte, Schlange , Dämonenfrosch), später dann bis zu 5 Gegner (Großer Zerberus, Dunkles Auge, ...).
- "Echtzeit" Kampfsystem: jede aktion steigert den Aktionscooldown des Helden/Gegners zu einem gewissen Wert, der erst einmal abklingen muss, bis er eine neue Aktion starten kann.
- Fullscreen mode (Alt+Enter drücken und er wird aktiviert)

Geplante Features?
- Zaubersprüche (davon wird es einige geben, aber das system muss ich erst noch einbauen. werde es wohl mit einem vektor und funktionspointern auf die spellfunktionen machen).
- Das "Flimmern" der karte entfernen :D (das muss auf jedenfall weg)
- Korrekte Startpositionsberechnung, wenn man die Karten wechselt (da gibt es derzeit einen bug, wenn man von den Tower Fields zurück zu den Outer Tower Fields geht, startet der Heor komplett falsch).
- Letzte Map "Tower of Aeanna" muss noch fertig gebaut werden mit Endboss etc :)
- mehr unterschiedliche Gegner und Gegnerattacken
- mehr unterschiedliche Gegenstände
- Rüstungswert, Ausweichen und Trefferquote

Steuerung?
- WASD zum steuern des charakters nach oben,unten usw.
- ALT: Ruft einen Screen auf mit den Werten eures Helden und anderen Informationen
- E: mit e sprecht ihr mit NPCs, wechselt zu anderen Karten, wenn ihr auf Pfeilen steht oder öffnet Truhen, etc.(das mit den Truhen ist noch nicht eingebaut)
- STRG LINKS: Speichert euren Spielstand(leider wird derzeit noch nicht die richtige karte abgespeichert, aber ich arbeite dran).
- ESC: beendet das spiel und wirft euch zurück ins hauptmenü

Bugs?
- Startpositionsberechnung von hero von Aeean auf Outer Towers
- Richtige Karte wird nicht abgespeichert(man startet beim laden immer in Eralda)
- Eingabe bei kämpfen wird biem ersten mal nicht gelöscht (beim ersten angriff steht immer eine zeichenkette von WASD characters da)



Eine version mit sounds, wollt ich euch jetzt ned antun, da das 100mb hätte:P deswegen bekommt ihr ne soundlose version. Es würde mich freuen, wenn ihr bischen testen würdet und feedback gebt und mir eventuell bei einigen codestellen hilfestellungen geben könntet. Es ist noch ned sonderlich viel, was man derzeit machen kann :D aber es ist soweit schon spielbar. ich werd den code und die exedatei anhängen.

Achja nochwas zu diesem "charakterbildschirm". Die werte in klammer, die nach den heldenwerten stehen bedeuten, wieviel von den punkten durch gegestände entstehen.

z.b.
Stärke: 7 (+3) bedeutet, dass der held 4 grundstärke hat und 3 zusatzstärke durch gegenstände bekommt.

auch bei den haendlern, werdet ihr diese klammern finden. in klammern steht dann der preis des Gegenstandes.

Screenshots

(Link)


Download
Altar of Shadows.rar
Sourcecode.rar
Aktuellste exe.Datei

grek40

Alter Hase

Beiträge: 1 491

Wohnort: Dresden

  • Private Nachricht senden

2

24.04.2007, 20:01

Also das flimmern und die Steuerung solltest du definitiv überarbeiten... ich hab in der 2. Map aufgegeben, weil es nervig wurde^^

Falls du irgendwo garnich weiter weißt meld dich... ich hab schon einiges an Experimenten und Lösungen für Konsolensteuerungsprobleme durch ;)

3

24.04.2007, 20:33

beim flimmern bräucht ich wirklich hilfe :)

derzeit zeichnet er immer ALLES neu, was eigentlich unnötig ist.

eigentlich bräuchte er nur 1x die map zeichnen und dann nur mehr heroes und enemies.

gibts da irgendwie so nen goto befehl? oder vl nur nen renewline befehl oder sowas? dann wär das flimmern glaub ich weg.

die steuerung? was hast du da zum aussetzen :P ist atm

if(GetAsycKeyState('bla')) iPositionX/Y++/--;

und halt nen sleep von 600 glaub ich zwischen den bewegungen, weil man ja irgendwie nicht so ne fps abhängige nachrichtenschleife in die konsole bauen kann oder? :D

aber wäre für hilfe offen :)

btw ist bei euch bei rapidshare auch son kack, dass man ne minute warten muss, refresehen und erst dann geht der dl? weil wenn ja lad ich das wo anders hoch, das ist ja irgendwie ne zumutung :)

aber danke fürs anspielen grek^^

mfg
Simon

Frede

Treue Seele

Beiträge: 259

Wohnort: Hameln

Beruf: Schüler

  • Private Nachricht senden

4

24.04.2007, 20:49

Hi
lad mir gleich ma dein Spiel, kann also noch nix dazu sagen.
Aber wegen deinem Goto-Problem: Das hatte ich auch als ich noch Konsole geproggt habe.

Das hier sollte dir helfen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
void gotoxy(short x, short y)
{
HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X=x-1;
pos.Y=y-1;
SetConsoleCursorPosition(hCon, pos); 
}


mfg Frede

Edit:
Fals du noch mehr über Hilfen zum Umgang mit der Konsole haben willst, guck ma da rein:
http://spieleprogrammierer.de/phpBB2/viewtopic.php?t=6968&highlight=konsole+farbe+gotoxy
Hier könnte ihre Werbung stehen.

grek40

Alter Hase

Beiträge: 1 491

Wohnort: Dresden

  • Private Nachricht senden

5

24.04.2007, 21:02

Also, da das alles ein Komplex ist poste ich mal meine aktuelle Lösung für Position, Farbe etc. in der Konsole... eine Funktion zum gesamtlöschen hab ich auch, die is aber hässlich, deswegen lass ich sie hier weg ;)
Zur Fehlerbehandlung verwende ich meine eigenen Exceptionmechanismen, deswegen kommentier ich hier die entsprechenden Stellen aus.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include <windows.h>
#include <iostream>

/*
#include <Exception.h>

#ifndef _UNICODE
#ifdef _DEBUG
#pragma comment(lib, "A_DebugLibD")
#else
#pragma comment(lib, "A_DebugLib")
#endif
#else
#ifdef _DEBUG
#pragma comment(lib, "U_DebugLibD")
#else
#pragma comment(lib, "U_DebugLib")
#endif
#endif
*/

namespace Console
{
    class Color
    {
        friend inline std::basic_ostream<TCHAR>& operator << (std::basic_ostream<TCHAR>& _os, const Color& _copy)
        {
//          DEBUG_STACK;

            if ( ! SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), _copy._color))
            {
//              EXCEPTION(Exception, _T("SetConsoleTextAttribute fehlgeschlagen."));

            }
            return _os;
        }
    public:
        Color(unsigned short color) : _color(color) {}
    private:
        unsigned short _color;
    };

    class Pos
    {
        friend std::basic_ostream<TCHAR>& operator << (std::basic_ostream<TCHAR>& _os, const Pos& _copy)
        {
//          DEBUG_STACK;

            if ( ! SetConsoleCursorPosition( GetStdHandle(STD_OUTPUT_HANDLE), _copy._pos ) )
            {
//              EXCEPTION(Exception, _T("SetConsoleCursorPosition fehlgeschlagen."));

            }
            return _os;
        }
    public:
        Pos(unsigned short x, unsigned short y)
        { _pos.X=x; _pos.Y=y; }
    private:
        COORD _pos;
    };

    class Cursor
    {
        friend std::basic_ostream<TCHAR>& operator << (std::basic_ostream<TCHAR>& _os, const Cursor& _copy)
        {
//          DEBUG_STACK;

            if ( ! SetConsoleCursorInfo( GetStdHandle(STD_OUTPUT_HANDLE), &(_copy._cursor) ) )
            {
//              EXCEPTION(Exception, _T("SetConsoleCursorInfo fehlgeschlagen."));

            }
            return _os;
        }
    public:
        Cursor(unsigned long size, bool visible=true)
        {
            if (size<1)
            { size=1; visible=false; }
            _cursor.dwSize=size;
            _cursor.bVisible=visible;
        }
    private:
        CONSOLE_CURSOR_INFO _cursor;
    };

    class Title
    {
        friend std::basic_ostream<TCHAR>& operator << (std::basic_ostream<TCHAR>& _os, const Title& _copy)
        {
//          DEBUG_STACK;

            if ( ! SetConsoleTitle( _copy._title.c_str() ) )
            {
//              EXCEPTION(Exception, _T("SetConsoleTitleW fehlgeschlagen."));

            }
            return _os;
        }
    public:
        Title(const TCHAR* title) : _title(title)
        {}
    private:
        std::basic_string<TCHAR> _title;
    };


    inline void displaysize( unsigned short _X, unsigned short _Y )
    {
//      DEBUG_STACK;

        HANDLE hCon = GetStdHandle( STD_OUTPUT_HANDLE );
        CONSOLE_SCREEN_BUFFER_INFO info;
        SMALL_RECT change = {0};
        if ( ! GetConsoleScreenBufferInfo( hCon, &info ) )
        {
//          EXCEPTION(Exception, _T("GetConsoleScreenBufferInfo fehlgeschlagen."));

        }
        if ( _X >= info.dwMaximumWindowSize.X )
            change.Right = info.dwMaximumWindowSize.X-1;
        else
            change.Right = _X;
        if ( _Y >= info.dwMaximumWindowSize.Y )
            change.Bottom = info.dwMaximumWindowSize.Y-1;
        else
            change.Bottom = _Y;
        if ( ! SetConsoleWindowInfo( hCon, true, &change ) )
        {
//          EXCEPTION(Exception, _T("SetConsoleWindowInfo fehlgeschlagen."));

        }
    }

    inline void buffersize( unsigned short _X, unsigned short _Y )
    {
//      DEBUG_STACK;

        COORD newSize = {_X, _Y};
        newSize.X=_X;
        newSize.Y=_Y;
        if ( ! SetConsoleScreenBufferSize( GetStdHandle(STD_OUTPUT_HANDLE), newSize ) )
        {
//          EXCEPTION(Exception, _T("SetConsoleScreenBufferSize fehlgeschlagen."));

        }
    }

}


Zur Verwendung:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
    Console::displaysize(80, 41);
    Console::buffersize (80, 42);
    std::wcout << Console::Title(L"Labyrinth v1.0");
    std::wcout
        << Console::Color(15)
        << Console::Pos(20, 10)
        << L"Herzlichen Glueckwunsch"
        << Console::Pos(18, 12)
        << L"Sie haben gewonnen!"
        << Console::Pos(20, 15)
        << L"Weiter gehts mit Return";


Wie du siehst, kann man häufige Sachen wie Farbwechsel und Positionswechsel direkt in den Stream integrieren. Die Farben lassen sich in bekannter Art angeben (FOREGROUND_RED...)

// toll, ewig lange geschrieben und dann steht schon ne Antwort da :D

6

25.04.2007, 11:28

super danke :)

also das flimmern ist jetzt weg :D, aber dafür gibts ein problem. komischerweise werden die gegner jetzt nicht mehr angezeigt, nachdem sie sich bewegen, sondern nur mehr der held

hier mal die funktion

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// function : drawUnits

void CMap::drawUnits()
{
    // Variables

    COORD iHeroPos;
    COORD iEnemyPos;    


    // Get current position

    Hero.getPosition((int*)(&iHeroPos.X), (int*)(&iHeroPos.Y));
    SetConsoleCursorPosition(hConsole, iHeroPos);
    // Draw hero

    DrawHero
    cout << "A";
    DrawStandard

    // Check position of enemies

    for(int i=0; i<iNumEnemies; i++)
    {
        g_Enemy[i].getPosition((int*)(&iEnemyPos.X), (int*)(&iEnemyPos.Y));
        SetConsoleCursorPosition(hConsole, iEnemyPos);
        // Draw enemy

        DrawEnemy
        cout << "E";
        DrawStandard
    }
}


die Draw sachen sind alles makros von SetConsoleTextAttribute oder wie das heißt :D

getPosition liefert die aktuelle position zurück und zeichnet den entsprechenden buchstaben an der position. mit dem SetCursorPosition gelang ich da jetzt direkt hin und brauch keine system("cls") mehr. in der move funktion von hero und enemy wird dann jeweils an der alten position des helden das entsprechende tile wieder nachgezeichnet.

wenn der held z.b. auf nem händler stand und sich wegbewegt, wird wieder das händlersymbol hingezeichnet und das "A" für hero an der neuen position.

tja nur bei den gegner will das nicht^^ die funktionen für held und gegner sehen komplett ident aus deswegen wundert mich das etwas :(

kann das vl an der erstellung der gegnergruppen liegen?

C-/C++-Quelltext

1
2
3
4
5
6
7
8
if(g_CurrentMap->iNumEnemies > 0)
    {
        if(g_Enemy != NULL)
            delete[] g_Enemy;
        g_Enemy = new CEnemyGroup[g_CurrentMap->iNumEnemies];
        for(int i=0; i<g_CurrentMap->iNumEnemies; i++)
            g_Enemy[i].setStartLocation();
    }

Currentmap ist die aktuelle map, inumenemies eben anzahl der gegner auf der karte. g_Enemy ist ein globaler pointer für EnemyGroups(gegnergruppen: beinhaltet information aus wievielen gegnern die gruppe besteht und aus welcher art). und setStarTLocation erstellt die gegner zufällig an einem erlaubten tile.

könnt ihr irgendwelche fehler entdecken ?:D

ich schaus mir sonst am abend und morgen nochmal an, vl hab ich irgendwas übersehen.

mfg
Simon :)

P.S.: ohne flimmern ist das schon gleich angenehmer zum spielen^^

grek40

Alter Hase

Beiträge: 1 491

Wohnort: Dresden

  • Private Nachricht senden

7

25.04.2007, 16:30

Zitat von »"Draculark"«


in der move funktion von hero und enemy wird dann jeweils an der alten position des helden das entsprechende tile wieder nachgezeichnet.


Wenn es eh grad Probleme mit dem Zeichnen gibt dann ist das ne gute gelegenheit, um gleich mal die neue Position auch mit in die move-funktion unterzubringen ;)

// wenn es jetzt angenehmer zu spielen ist dann ma her mit neuer Version :)

8

25.04.2007, 16:36

kewl frag mich ned waurm, aber hab jetzt die meisten int PosX, PosY auf COORD geändert und jetzt funktioniert die gegnerdarstellung plötzlich wieder:D

k ich lad mal die entflimmerte version hoch^^

bei fehlern oder so bitte melden, dann änder ich bei den klassen das PosX,Y auch frisch gleich auf COORD um, denn kA wie fehleranfällig das ist, wenn der da manchmal COORD(short oder?) in int umwandelt :D

edit: ach nochwas was gewaltig stört irgendwie. wenn ein kampf beginnt, und man gefragt wird welchen gegner man attacken möchte, steht zuerst die WASD zeichenfolge da, die man auf der map gedrückt hat.

gibts nen befehl, der die eingabe auf 0 resettet? habs schon mit cin.clear, cout.flush, cout \n\r, cin.clear() probiert, das hilft aber irgendwie alles nicht^^

edit2:

so neue version oben angehängt unter Aktuellste exe.datei
es gibt derzeit n problem , dass wenn man auf ne karte mit monstern geht, dass dann ein error entsteht. ich vermute derzeit,dass es daran liegt, dass ich entweder a) die größe der karte nicht richtig berechne oder b) dass die gegner manchmal falsch spawnen und das nen fehler verursacht (tippe aber irgendwie mehr auf das erste:P).

Neu in dieser version:
- Flimmern ist weg

edit3:

so nochmal jetzt ne neue version oben angehängt :D
hab zum ersten mal vcon winxp bei der fehlermeldung die funktion debug benutzt. dachte immer die bringt nichts, aber die lief perfekt:D und hat mich direkt zu den fehlern gebracht :D
sollten jetzt behoben sein.
fehler war,dass teilweise beim 2D array auf felder kleiner 0 bzw größer der maximalgröße des arrays zugegriffen wurde :) denke das hab ich behoben :D

viel spaß also weiterhin.

als nächstes werden dann wohl die spells folgen, die das spiel dann erst richtig "aufregend" machen und ein endboss :)

grek40

Alter Hase

Beiträge: 1 491

Wohnort: Dresden

  • Private Nachricht senden

9

25.04.2007, 20:04

1. Du musst deine Eingabe nochmal überarbeiten.

1.1. Ich bin irgendwann immer an den Punkt gekommen, wo sich die Eingaben verselbständigt haben (Im Kampf konnte ich nix mehr steuern)
Das hängt meistens damit zusammen, dass man direkt ein int o.ä. einliest und der Spieler nen Buchstaben eingibt... entweder machst du im Zusammenhang mit der Eingabe ne Fehlerbehandlung oder du liest immer Buchstaben ein und konvertierst dann in eine Zahl.

1.2. Ich vermute mal, du steuerst vieles mit

C-/C++-Quelltext

1
2
if (GetAsyncKeyState(...))
  // dann mach was

Versuch mal stattdessen

C-/C++-Quelltext

1
2
if (GetAsyncKeyState(...) & 0x8000)
  // dann passiert wirklich was

Das hat den Vorteil, dass du wirklich nur auf aktuelle Tastendrucke reagierst anstatt irgendwelche Eingaben seit der letzten Abfrage. Wenn du es ganz anders machst dann solltest du trotzdem was ändern^^

2. Darstellung

2.1. Warum kann man mehr Zauberaktionen als maximale Zauberaktionen haben? -> Kampfzauberer Spezialisierung

2.2. Einige Gegner werden nach einem Kampf nicht mit Landschaft übermalt -> Nachholbedarf

3. Die Tränke sind ziemlich sinnlos, wenn du uns nicht verrätst wie man sie trinkt - oder kann man sie noch nicht trinken?

... gibt sicher noch mehr, aber ich habs grad wieder vergessen / noch nicht bemerkt

10

25.04.2007, 21:18

@1. hm ich dachte das hätte ich behoben.

ich zeig dir mal kurz den code :D

C-/C++-Quelltext

1
2
3
4
if(GetAsyncKeyState('W'))               CurrentPos.Y--;
    else if(GetAsyncKeyState('S'))  CurrentPos.Y++;
    else if(GetAsyncKeyState('A'))  CurrentPos.X--;
    else if(GetAsyncKeyState('D'))  CurrentPos.X++;


das ist die bwegeung. nichts aufregendes. meinst du das da schon mit der zahlenüberprüfung?

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Variables

    int iTarget = 0;

    
    cout << "Auf welchen Gegner wollt ihr die Attacke starten?\n";
    for(int i=0; i<iNumMonsters; i++)
    {
        if(g_Fighters[i]->getName() != "Noone")
            cout << i+1 << "." << g_Fighters[i]->getName() << "\n";
    }
    cin.clear();
    cin.sync();
    cin >> iTarget;
 
    if(iTarget==0 || iTarget > iNumMonsters)
        cout << "Fehler in der Eingabe!\n";
    else
    {
        // Start attack

        wcout << stName;
        cout << " greift an!\n";
        issueDamage(g_Fighters[iTarget-1]);
    }

das wär dann die abfrage im kampf. mit cin.clear und cin.sync wird doch eigentlich ne falsch eingabe wieder weggelöscht bzw. "vergessen" und somit diese endlosschleife unterbrochen, die eigentlich auftritt, wenn man statt ner zahl nen buchstaben eingibt. zumindest war das bei meinem test so :P

@2: danke, das wär mir wohl nicht aufgefallen. die maxSpellpoints hab ich erst später ergänzt und somit mach ich damit noch nichts :D danke
das mit den gegner schau ich mir auch nochmal an, hab da noch ne idee, dann sollte es aber wirklich soweit gut gehn :-)

@3: ja tränke kann man noch ned benutzen... aehm eigentlich wollt ich das machen, bevor ich es hier präsentiere, aber wieder vergessen sry:P wird aber in die nächste version fix eingebaut. werds wohl bis spätestens freitag schaffen denk ich :)


danke jedenfalls wieder fürs testen :)

greetings :)

Werbeanzeige