source: trunk/monsterz/piece.cpp @ 263

Last change on this file since 263 was 263, checked in by sam, 10 years ago

Spawn new pieces at the correct coordinates for a free fall.

File size: 4.6 KB
Line 
1//
2// Monsterz
3//
4// Copyright: (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
9//
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include <cstdio>
16#include <cmath>
17
18#include "core.h"
19#include "piece.h"
20#include "monsterz.h"
21
22/*
23 * Piece implementation class
24 */
25
26class PieceData
27{
28    friend class Piece;
29
30private:
31    Game *game;
32    int tiler;
33    Int2 cell, pos, src, dst;
34    int id;
35    float speed, timer;
36
37    enum
38    {
39        IDLE,
40        BLINK,
41        GRAB,
42        UNGRAB,
43        MOVE,
44    }
45    state;
46};
47
48/*
49 * Public Piece class
50 */
51
52Piece::Piece(Game *game, Int2 cell, int id)
53  : data(new PieceData())
54{
55    data->game = game;
56    Ticker::Ref(game);
57    data->tiler = Tiler::Register(PNG_TILES, 48, 48, 1.0f);
58    data->cell = cell;
59    data->pos = cell * 48;
60    data->id = id;
61    data->state = PieceData::IDLE;
62}
63
64void Piece::SetCell(Int2 cell)
65{
66    data->cell = cell;
67}
68
69Int2 Piece::GetCell() const
70{
71    return data->cell;
72}
73
74void Piece::SetPos(Int2 pos)
75{
76    data->pos = pos;
77}
78
79Int2 Piece::GetPos() const
80{
81    return data->pos;
82}
83
84int Piece::GetId() const
85{
86    return data->id;
87}
88
89int Piece::Blink()
90{
91    switch (data->state)
92    {
93    case PieceData::IDLE:
94        data->state = PieceData::BLINK;
95        data->timer = 400.0f; /* Duration of a blink */
96        return 1;
97    default:
98        return 0;
99    }
100}
101
102int Piece::Pop()
103{
104    return 0;
105}
106
107int Piece::Grab(Int2 dir)
108{
109    switch (data->state)
110    {
111    case PieceData::UNGRAB:
112    case PieceData::MOVE:
113        /* Only allow swaps when piece is close enough to its target cell. */
114        if ((data->cell * 48 - data->pos).sqlen() > 24 * 24)
115            return 0;
116        /* Fall through */
117    case PieceData::IDLE:
118    case PieceData::BLINK:
119    case PieceData::GRAB:
120        data->state = PieceData::GRAB;
121        data->pos = data->pos + dir;
122        return 1;
123    default:
124        return 0;
125    }
126}
127
128int Piece::Ungrab()
129{
130    switch (data->state)
131    {
132    case PieceData::GRAB:
133        data->state = PieceData::UNGRAB;
134        data->speed = 0.3f;
135        data->timer = 0.0f;
136        data->src = data->pos;
137        data->dst = data->cell * 48;
138        return 1;
139    default:
140        return 0;
141    }
142}
143
144int Piece::Goto(Int2 pos, float speed)
145{
146    switch (data->state)
147    {
148    case PieceData::IDLE:
149    case PieceData::BLINK:
150    case PieceData::UNGRAB:
151    case PieceData::MOVE:
152        data->state = PieceData::MOVE;
153        data->timer = 0.0f;
154        data->src = data->pos;
155        data->dst = pos;
156        data->speed = speed;
157        return 1;
158    case PieceData::GRAB:
159    default:
160        return 0;
161    }
162}
163
164void Piece::TickGame(float deltams)
165{
166    switch (data->state)
167    {
168    case PieceData::IDLE:
169        break;
170    case PieceData::BLINK:
171        data->timer -= deltams;
172        if (data->timer < 0.0f)
173            data->state = PieceData::IDLE;
174        break;
175    case PieceData::GRAB:
176        break;
177    case PieceData::UNGRAB:
178    case PieceData::MOVE:
179        data->timer += deltams;
180        Int2 trip = data->dst - data->src;
181        float moving_time = trip.len() / data->speed;
182        float t = moving_time ? data->timer / moving_time : 1.0f;
183        if (t >= 1.0f)
184            t = 1.0f;
185        if (data->timer > moving_time + 200.0f)
186            data->state = PieceData::IDLE;
187        t = t * t * 3 - t * t * t * 2;
188        t = t * t * 3 - t * t * t * 2;
189        data->pos = data->src + (t * trip + 0.5f);
190        break;
191    }
192    Entity::TickGame(deltams);
193}
194
195void Piece::TickDraw(float deltams)
196{
197    Entity::TickDraw(deltams);
198
199    int id = data->id;
200    int x = data->pos.x + 24;
201    int y = data->pos.y + 177;
202    int z = 2;
203
204    /* Optional modifiers */
205    switch (data->state)
206    {
207    case PieceData::IDLE:
208        break;
209    case PieceData::BLINK:
210        id = data->id + 1;
211        break;
212    case PieceData::GRAB:
213        id = data->id + 1;
214        z = 4;
215        break;
216    case PieceData::UNGRAB:
217        if ((data->cell * 48 - data->src).sqlen() > 24 * 24)
218            id = data->id + 2;
219        z = 4;
220        break;
221    case PieceData::MOVE:
222        z = 3;
223        break;
224    }
225
226    data->game->GetScene()->AddTile((data->tiler << 16) | id, x, y, z, 0);
227
228    if (data->state == PieceData::GRAB)
229        data->game->GetScene()->AddTile((data->tiler << 16) | 0, x, y, 5, 0);
230}
231
232Piece::~Piece()
233{
234    Ticker::Unref(data->game);
235    Tiler::Deregister(data->tiler);
236    delete data;
237}
238
Note: See TracBrowser for help on using the repository browser.