1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or(at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "ags/plugins/ags_parallax/ags_parallax.h"
24 #include "ags/shared/core/platform.h"
25 #include "common/endian.h"
26 
27 namespace AGS3 {
28 namespace Plugins {
29 namespace AGSParallax {
30 
31 const unsigned int Magic = 0xCAFE0000;
32 const unsigned int Version = 2;
33 const unsigned int SaveMagic = Magic + Version;
34 
AGS_GetPluginName()35 const char *AGSParallax::AGS_GetPluginName() {
36 	return "Parallax plugin recreation";
37 }
38 
AGS_EngineStartup(IAGSEngine * engine)39 void AGSParallax::AGS_EngineStartup(IAGSEngine *engine) {
40 	PluginBase::AGS_EngineStartup(engine);
41 
42 	if (_engine->version < 13)
43 		_engine->AbortGame("Engine interface is too old, need newer version of AGS.");
44 
45 	SCRIPT_METHOD(pxDrawSprite, AGSParallax::pxDrawSprite);
46 	SCRIPT_METHOD(pxDeleteSprite, AGSParallax::pxDeleteSprite);
47 
48 	_engine->RequestEventHook(AGSE_PREGUIDRAW);
49 	_engine->RequestEventHook(AGSE_PRESCREENDRAW);
50 	_engine->RequestEventHook(AGSE_ENTERROOM);
51 	_engine->RequestEventHook(AGSE_SAVEGAME);
52 	_engine->RequestEventHook(AGSE_RESTOREGAME);
53 }
54 
AGS_EngineOnEvent(int event,NumberPtr data)55 int64 AGSParallax::AGS_EngineOnEvent(int event, NumberPtr data) {
56 	if (event == AGSE_PREGUIDRAW) {
57 		Draw(true);
58 	} else if (event == AGSE_PRESCREENDRAW) {
59 		// Get screen size and then draw
60 		_engine->GetScreenDimensions(&_screenWidth, &_screenHeight, &_screenColorDepth);
61 		Draw(false);
62 	} else if (event == AGSE_ENTERROOM) {
63 		// Reset all _sprites
64 		clear();
65 	} else if (event == AGSE_RESTOREGAME) {
66 		Serializer s(_engine, data, true);
67 		syncGame(s);
68 	} else if (event == AGSE_SAVEGAME) {
69 		Serializer s(_engine, data, false);
70 		syncGame(s);
71 	}
72 
73 	return 0;
74 }
75 
clear()76 void AGSParallax::clear() {
77 	for (int i = 0; i < MAX_SPRITES; i++) {
78 		_sprites[i] = Sprite();
79 		_sprites[i].slot = -1;
80 	}
81 
82 	_enabled = false;
83 }
84 
syncGame(Serializer & s)85 void AGSParallax::syncGame(Serializer &s) {
86 	int saveVersion = SaveMagic;
87 	s.syncAsInt(saveVersion);
88 	if ((uint)saveVersion != SaveMagic) {
89 		_engine->AbortGame("ags_parallax: bad save.");
90 		return;
91 	}
92 
93 	for (int i = 0; i < MAX_SPRITES; ++i)
94 		_sprites[i].syncGame(s);
95 	s.syncAsBool(_enabled);
96 }
97 
Draw(bool foreground)98 void AGSParallax::Draw(bool foreground) {
99 	if (!_enabled)
100 		return;
101 
102 	BITMAP *bmp;
103 	int i;
104 
105 	int32 offsetX = 0;
106 	int32 offsetY = 0;
107 	_engine->ViewportToRoom(&offsetX, &offsetY);
108 
109 	for (i = 0; i < MAX_SPRITES; i++) {
110 		if (_sprites[i].slot > -1) {
111 			if (foreground) {
112 				if (_sprites[i].speed > 0) {
113 					bmp = _engine->GetSpriteGraphic(_sprites[i].slot);
114 					if (bmp)
115 						_engine->BlitBitmap(_sprites[i].x - offsetX - (_sprites[i].speed * offsetX / 100), _sprites[i].y, bmp, 1);
116 				}
117 			} else {
118 				if (_sprites[i].speed <= 0) {
119 					bmp = _engine->GetSpriteGraphic(_sprites[i].slot);
120 					if (bmp)
121 						_engine->BlitBitmap(_sprites[i].x - offsetX - (_sprites[i].speed * offsetX / 1000), _sprites[i].y, bmp, 1);
122 				}
123 			}
124 		}
125 	}
126 }
127 
pxDrawSprite(ScriptMethodParams & params)128 void AGSParallax::pxDrawSprite(ScriptMethodParams &params) {
129 	PARAMS5(int, id, int, x, int, y, int, slot, int, speed);
130 
131 	if ((id < 0) || (id >= MAX_SPRITES))
132 		return;
133 
134 	if ((speed < -MAX_SPEED) || (speed > MAX_SPEED))
135 		speed = 0;
136 
137 	_sprites[id].x = x;
138 	_sprites[id].y = y;
139 	_sprites[id].slot = slot;
140 	_sprites[id].speed = speed;
141 
142 	_engine->RoomToViewport(&_sprites[id].x, &_sprites[id].y);
143 
144 	_enabled = true;
145 }
146 
147 
pxDeleteSprite(ScriptMethodParams & params)148 void AGSParallax::pxDeleteSprite(ScriptMethodParams &params) {
149 	PARAMS1(int, id);
150 
151 	if ((id < 0) || (id >= MAX_SPRITES))
152 		return;
153 
154 	_sprites[id].slot = -1;
155 }
156 
157 /*------------------------------------------------------------------*/
158 
syncGame(Serializer & s)159 void Sprite::syncGame(Serializer &s) {
160 	s.syncAsInt(x);
161 	s.syncAsInt(y);
162 	s.syncAsInt(slot);
163 	s.syncAsInt(speed);
164 }
165 
166 } // namespace AGSParallax
167 } // namespace Plugins
168 } // namespace AGS3
169