Skip to content

Commit 2af0e21

Browse files
committed
The zoom levels now depend on the amount of area shown, regardless of window resolution.
- The best solution I could find to the problem of the game maker specifying how far the camera should see, but the player being able to see farther with weird resolutions, is to forget how "far" and focus on the total area of visible world pixels. - Closes #7.
1 parent 37dfbdf commit 2af0e21

File tree

17 files changed

+89
-70
lines changed

17 files changed

+89
-70
lines changed

game_data/base/misc/config.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,6 @@ rules {
6060
throw_max_dist = 200
6161
whistle_growth_speed = 180
6262
whistle_max_dist = 200
63-
zoom_max_level = 3.0
64-
zoom_min_level = 0.66
63+
zoom_closest_reach = 295
64+
zoom_farthest_reach = 1340
6565
}

manual/content/changelog.html

+2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ <h2 id="0.26.0">0.26.0</h2>
4444
<li><span class="cl-c">Changed</span> the appearance of water to be more dynamic (using shaders). (Thanks Helodity)</li>
4545
<li><span class="cl-c">Changed</span> how options are organized in the options file, so you may have to set them again.</li>
4646
<li><span class="cl-c">Changed</span> some properties and behaviors of some enemies to make them easier to fight.</li>
47+
<li><span class="cl-c">Changed</span> how window resolutions are handled. The same general amount of area pixels are shown regardless of resolution. i.e. at higher resolutions the player will see things sharper instead of seeing farther than normal.</li>
4748
</ul>
4849

4950
<p><b>Content-making changes</b></p>
@@ -143,6 +144,7 @@ <h2 id="0.26.0">0.26.0</h2>
143144
<li><span class="cl-c">Changed</span> the names of the control-binds related <a href="gui.html">GUI items</a> in the options menu.</li>
144145
<li><span class="cl-c">Changed</span> the amount of hazards that a <a href="area.html">sector</a> or a <a href="animation.html">hitbox</a> can have to 1. Their properties were thus renamed from <code>hazards</code> to <code>hazard</code>.</li>
145146
<li><span class="cl-c">Changed</span> the name of the "screen" limit properties of the <a href="gui.html">title screen GUI's</a> logo block to read "window" instead.</li>
147+
<li><span class="cl-c">Changed</span> the zoom-level properties of the <a href="game_config.html">game configuration</a> and <a href="options.html">options</a> to instead be about the "reach", and renamed to <code>zoom_*_reach</code> accordingly.</li>
146148
</li>
147149
</ul>
148150

manual/content/game_config.html

+6-6
Original file line numberDiff line numberDiff line change
@@ -313,16 +313,16 @@ <h2 id="rules">Rules</h2>
313313
<td>200</td>
314314
</tr>
315315
<tr>
316-
<td>zoom_max_level</td>
317-
<td>Maximum level of zoom (i.e. how close the camera can get).</td>
316+
<td>zoom_closest_reach</td>
317+
<td>At the closest zoom level, the camera shows an area depending on this value, in world pixels. You can think of this as "on average, the player has a horizontal view span or vertical view span of this amount". The area is calculated as this value squared.<br>Because different window resolutions can show more on one direction than another, and because the corners of the window show much farther than the sides, it's no use trying to control exactly how <i>far</i> the player sees, and so <i>Pikifen</i> instead focuses on the <i>total area</i> of visible world pixels at any moment. As an example, for an area of 87'025 pixels (295 squared), on a square window resolution like 1024x1024, the player will see 295 pixels far horizontally and 295 vertically. On a 16:9 resolution like 1024x768, the player will see around 340 horizontally and 256 vertically (around 87'040 pixels).</td>
318318
<td>Number</td>
319-
<td>3</td>
319+
<td>295</td>
320320
</tr>
321321
<tr>
322-
<td>zoom_min_level</td>
323-
<td>Minimum level of zoom (i.e. how far away the camera can get).</td>
322+
<td>zoom_farthest_level</td>
323+
<td>Same as <code>zoom_closest_reach</code>, but for the farthest zoom level.</td>
324324
<td>Number</td>
325-
<td>0.66</td>
325+
<td>1340</td>
326326
</tr>
327327
</table>
328328

manual/content/history.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
<h2 id="creation">Creation</h2>
2020

21-
<p>The idea for the engine started on mid 2013, with the intent of both allowing <i>Pikmin</i> fans to make their own games reality as well as to create a fun and challenging <i>Pikmin</i>-related project. The idea was made public on Pikmin Fanon, where <a href="https://www.pikminfanon.com/wiki/Topic:Pikmin_Engine_by_Espyo">a topic</a> was created to gather feedback, before starting the project. On the 15th of August, 2013, development of the engine officially began. Ever since, different versions have been released, each one more complete than the last.</p>
21+
<p>The idea for the engine started on mid-2013, with the intent of both allowing <i>Pikmin</i> fans to make their own games reality as well as to create a fun and challenging <i>Pikmin</i>-related project. The idea was made public on Pikmin Fanon, where <a href="https://www.pikminfanon.com/wiki/Topic:Pikmin_Engine_by_Espyo">a topic</a> was created to gather feedback, before starting the project. On the 15th of August, 2013, development of the engine officially began. Ever since, different versions have been released, each one more complete than the last.</p>
2222

2323
<p>On February 2nd, 2018, the project got rebranded, and the mission statement changed a bit. Instead of it being called "Pikmin fangame engine", it got renamed to "<i>Pikifen</i>", and the idea was no longer to make fan games a reality, since that proved to be too ambitious at best, and outright impossible at worst. Instead, the goal became to create a fun engine in which people could create and play their own content, and the idea to make full games in it being secondary.</p>
2424

manual/content/options.html

+6-6
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,6 @@ <h2 id="advanced">Advanced</h2>
6161
<td>Number</td>
6262
<td>1000</td>
6363
</tr>
64-
<tr>
65-
<td><code>middle_zoom_level</code></td>
66-
<td>When pressing the camera button, the zoom level swaps between near, far, and this amount.</td>
67-
<td>Number</td>
68-
<td>1.50</td>
69-
</tr>
7064
<tr>
7165
<td><code>mipmaps</code></td>
7266
<td><code>true</code> to enable <a href="http://en.wikipedia.org/wiki/Mipmap">mipmaps</a>, <code>false</code> to disable them. Enabling them is recommended, and increases VRAM usage for slightly less GPU usage. Turn it off if you need RAM. Might affect performance.</td>
@@ -109,6 +103,12 @@ <h2 id="advanced">Advanced</h2>
109103
<td>Boolean</td>
110104
<td>false</td>
111105
</tr>
106+
<tr>
107+
<td><code>zoom_medium_reach</code></td>
108+
<td>Same as the <code>zoom_closest_reach</code> <a href="game_config.html#rules">game configuration property</a>, but for the medium zoom level.</td>
109+
<td>Number</td>
110+
<td>630</td>
111+
</tr>
112112
</table>
113113

114114
<h2 id="animation-editor">Animation editor</h2>

source/documents/misc_info.txt

+1-2
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,7 @@ Bag of notes (useful stuff)
116116
Ideas for representing height
117117
Distant sectors (above, below, or both?) could have fog drawn on top of them
118118
What about upscaling the game?
119-
Forget it. It's an insane headache. Between changing all of the file formats, variables, constants, etc. to the new numbers, you'd have to update the SVG and PNG files, and there are other tiny code problems that aren't immediately apparent. Players can just increase the resolution and zoom_mid_level.
120-
What if a higher resolution zooms in the game further (except for the HUD and menus and such), and zoom_mid_level can be used to see more or less by default? This makes sense, since if the game's min zoom is 0.5, that's because the creator doesn't want you to see too far.
119+
Forget it. It's an insane headache. Between changing all of the file formats, variables, constants, etc. to the new numbers, you'd have to update the SVG and PNG files, and there are other tiny code problems that aren't immediately apparent. Players can just increase the resolution and zoom_medium_reach.
121120
Pathing
122121
The only possible way to calculate the stops is by doing it first, before paths. If the engine could decide any stop at will, then were would the threshold be? What would stop it from deciding the last stop is like on the opposite side of the map from the target spot?
123122
Mobs that care about paths can only be in one of two stats: moving, or stuck

source/source/content/area/mission.cpp

+9-9
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ bool MissionFailKillEnemies::getEndZoomData(
8383
) const {
8484
if(gameplay->lastEnemyKilledPos.x != LARGE_FLOAT) {
8585
*out_cam_pos = gameplay->lastEnemyKilledPos;
86-
*out_cam_zoom = game.config.rules.zoomMaxLevel;
86+
*out_cam_zoom = gameplay->zoomLevels[0];
8787
return true;
8888
}
8989
return false;
@@ -228,7 +228,7 @@ bool MissionFailLoseLeaders::getEndZoomData(
228228
) const {
229229
if(gameplay->lastHurtLeaderPos.x != LARGE_FLOAT) {
230230
*out_cam_pos = gameplay->lastHurtLeaderPos;
231-
*out_cam_zoom = game.config.rules.zoomMaxLevel;
231+
*out_cam_zoom = gameplay->zoomLevels[0];
232232
return true;
233233
}
234234
return false;
@@ -371,7 +371,7 @@ bool MissionFailLosePikmin::getEndZoomData(
371371
) const {
372372
if(gameplay->lastPikminDeathPos.x != LARGE_FLOAT) {
373373
*out_cam_pos = gameplay->lastPikminDeathPos;
374-
*out_cam_zoom = game.config.rules.zoomMaxLevel;
374+
*out_cam_zoom = gameplay->zoomLevels[0];
375375
return true;
376376
}
377377
return false;
@@ -639,7 +639,7 @@ bool MissionFailTakeDamage::getEndZoomData(
639639
) const {
640640
if(gameplay->lastHurtLeaderPos.x != LARGE_FLOAT) {
641641
*out_cam_pos = gameplay->lastHurtLeaderPos;
642-
*out_cam_zoom = game.config.rules.zoomMaxLevel;
642+
*out_cam_zoom = gameplay->zoomLevels[0];
643643
return true;
644644
}
645645
return false;
@@ -933,7 +933,7 @@ bool MissionFailTooFewPikmin::getEndZoomData(
933933
) const {
934934
if(gameplay->lastPikminDeathPos.x != LARGE_FLOAT) {
935935
*out_cam_pos = gameplay->lastPikminDeathPos;
936-
*out_cam_zoom = game.config.rules.zoomMaxLevel;
936+
*out_cam_zoom = gameplay->zoomLevels[0];
937937
return true;
938938
}
939939
return false;
@@ -1076,7 +1076,7 @@ bool MissionFailTooManyPikmin::getEndZoomData(
10761076
) const {
10771077
if(gameplay->lastPikminBornPos.x != LARGE_FLOAT) {
10781078
*out_cam_pos = gameplay->lastPikminBornPos;
1079-
*out_cam_zoom = game.config.rules.zoomMaxLevel;
1079+
*out_cam_zoom = gameplay->zoomLevels[0];
10801080
return true;
10811081
}
10821082
return false;
@@ -1231,7 +1231,7 @@ bool MissionGoalBattleEnemies::getEndZoomData(
12311231
) const {
12321232
if(gameplay->lastEnemyKilledPos.x != LARGE_FLOAT) {
12331233
*out_cam_pos = gameplay->lastEnemyKilledPos;
1234-
*out_cam_zoom = game.config.rules.zoomMaxLevel;
1234+
*out_cam_zoom = gameplay->zoomLevels[0];
12351235
return true;
12361236
}
12371237
return false;
@@ -1383,7 +1383,7 @@ bool MissionGoalCollectTreasures::getEndZoomData(
13831383
) const {
13841384
if(gameplay->lastShipThatGotTreasurePos.x != LARGE_FLOAT) {
13851385
*out_cam_pos = gameplay->lastShipThatGotTreasurePos;
1386-
*out_cam_zoom = game.config.rules.zoomMaxLevel;
1386+
*out_cam_zoom = gameplay->zoomLevels[0];
13871387
return true;
13881388
}
13891389
return false;
@@ -1850,7 +1850,7 @@ bool MissionGoalGrowPikmin::getEndZoomData(
18501850
) const {
18511851
if(gameplay->lastPikminBornPos.x != LARGE_FLOAT) {
18521852
*out_cam_pos = gameplay->lastPikminBornPos;
1853-
*out_cam_zoom = game.config.rules.zoomMaxLevel;
1853+
*out_cam_zoom = gameplay->zoomLevels[0];
18541854
return true;
18551855
}
18561856
return false;

source/source/core/game_config.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,11 @@ const float WHISTLE_GROWTH_SPEED = 180.0f;
147147
//Default value for the maximum whistle distance.
148148
const float WHISTLE_MAX_DIST = CURSOR_MAX_DIST;
149149

150-
//Default value for the maximum zoom level.
151-
const float ZOOM_MAX_LEVEL = 3.0f;
150+
//Default value for the zoom closest reach.
151+
const float ZOOM_CLOSEST_REACH = 295.0f;
152152

153-
//Default value for the minimum zoom level.
154-
const float ZOOM_MIN_LEVEL = 0.66f;
153+
//Default value for the zoom farthest reach.
154+
const float ZOOM_FARTHEST_REACH = 1340.0f;
155155

156156
}
157157

@@ -263,7 +263,7 @@ void GameConfig::load(DataNode* file) {
263263
rrs.set("throw_max_dist", rules.throwMaxDist);
264264
rrs.set("whistle_growth_speed", rules.whistleGrowthSpeed);
265265
rrs.set("whistle_max_dist", rules.whistleMaxDist);
266-
rrs.set("zoom_max_level", rules.zoomMaxLevel);
267-
rrs.set("zoom_min_level", rules.zoomMinLevel);
266+
rrs.set("zoom_closest_reach", rules.zoomClosestReach);
267+
rrs.set("zoom_farthest_reach", rules.zoomFarthestReach);
268268
}
269269
}

source/source/core/game_config.h

+8-6
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ extern const size_t MAX_PIKMIN_IN_FIELD;
8181
extern const float THROW_MAX_DIST;
8282
extern const float WHISTLE_GROWTH_SPEED;
8383
extern const float WHISTLE_MAX_DIST;
84-
extern const float ZOOM_MAX_LEVEL;
85-
extern const float ZOOM_MIN_LEVEL;
84+
extern const float ZOOM_CLOSEST_REACH;
85+
extern const float ZOOM_FARTHEST_REACH;
8686
}
8787

8888
}
@@ -270,11 +270,13 @@ struct GameConfig {
270270
//Maximum distance from the leader that the whistle can start from.
271271
float whistleMaxDist = RULES_D::WHISTLE_MAX_DIST;
272272

273-
//The closest zoom level the player can get.
274-
float zoomMaxLevel = RULES_D::ZOOM_MAX_LEVEL;
273+
//The camera reach for the closest zoom level. In reality,
274+
//the camera keeps on-view an area of these many pixels squared.
275+
float zoomClosestReach = RULES_D::ZOOM_CLOSEST_REACH;
275276

276-
//The farthest zoom level the player can get.
277-
float zoomMinLevel = RULES_D::ZOOM_MIN_LEVEL;
277+
//The camera reach for the farthest zoom level. In reality,
278+
//the camera keeps on-view an area of these many pixels squared.
279+
float zoomFarthestReach = RULES_D::ZOOM_FARTHEST_REACH;
278280

279281
} rules;
280282

source/source/core/init.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -937,11 +937,11 @@ void initMisc() {
937937
game.states.gameplay->particles =
938938
ParticleManager(game.options.advanced.maxParticles);
939939

940-
game.options.advanced.zoomMidLevel =
940+
game.options.advanced.zoomMediumReach =
941941
std::clamp(
942-
game.options.advanced.zoomMidLevel,
943-
game.config.rules.zoomMinLevel,
944-
game.config.rules.zoomMaxLevel
942+
game.options.advanced.zoomMediumReach,
943+
game.config.rules.zoomClosestReach,
944+
game.config.rules.zoomFarthestReach
945945
);
946946

947947
game.liquidLimitEffectBuffer = al_create_bitmap(game.winW, game.winH);

source/source/core/options.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ const unsigned int TARGET_FPS = 60;
5353
//Default value for whether to use the window position hack.
5454
const bool WINDOW_POS_HACK = false;
5555

56-
//Default value for the middle zoom level.
57-
const float ZOOM_MID_LEVEL = 1.4f;
56+
//Default value for the zoom medium reach.
57+
const float ZOOM_MEDIUM_REACH = 630.0f;
5858

5959
}
6060

@@ -241,7 +241,6 @@ void Options::loadFromDataNode(DataNode* file) {
241241
ars.set("joystick_max_deadzone", advanced.joystickMaxDeadzone);
242242
ars.set("joystick_min_deadzone", advanced.joystickMinDeadzone);
243243
ars.set("max_particles", advanced.maxParticles);
244-
ars.set("middle_zoom_level", advanced.zoomMidLevel);
245244
ars.set("mipmaps", advanced.mipmapsEnabled);
246245
for(unsigned char p = 0; p < MAX_PLAYERS; p++) {
247246
ars.set(
@@ -251,6 +250,7 @@ void Options::loadFromDataNode(DataNode* file) {
251250
}
252251
ars.set("smooth_scaling", advanced.smoothScaling);
253252
ars.set("window_position_hack", advanced.windowPosHack);
253+
ars.set("zoom_medium_reach", advanced.zoomMediumReach);
254254

255255
advanced.targetFps = std::max(LOWEST_FRAMERATE, advanced.targetFps);
256256

@@ -509,7 +509,6 @@ void Options::saveToDataNode(DataNode* file) const {
509509
agw.write("joystick_max_deadzone", advanced.joystickMaxDeadzone);
510510
agw.write("joystick_min_deadzone", advanced.joystickMinDeadzone);
511511
agw.write("max_particles", advanced.maxParticles);
512-
agw.write("middle_zoom_level", advanced.zoomMidLevel);
513512
agw.write("mipmaps", advanced.mipmapsEnabled);
514513
for(unsigned char p = 0; p < MAX_PLAYERS; p++) {
515514
agw.write(
@@ -519,6 +518,7 @@ void Options::saveToDataNode(DataNode* file) const {
519518
}
520519
agw.write("smooth_scaling", advanced.smoothScaling);
521520
agw.write("window_position_hack", advanced.windowPosHack);
521+
agw.write("zoom_medium_reach", advanced.zoomMediumReach);
522522
}
523523

524524
//Animation editor.

source/source/core/options.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ extern const bool MOUSE_MOVES_CURSOR[MAX_PLAYERS];
7474
extern const bool SMOOTH_SCALING;
7575
extern const unsigned int TARGET_FPS;
7676
extern const bool WINDOW_POS_HACK;
77-
extern const float ZOOM_MID_LEVEL;
77+
extern const float ZOOM_MEDIUM_REACH;
7878
}
7979

8080
namespace AUDIO_D {
@@ -195,7 +195,7 @@ struct Options {
195195
bool windowPosHack = ADVANCED_D::WINDOW_POS_HACK;
196196

197197
//Set the camera's middle zoom level to this amount.
198-
float zoomMidLevel = ADVANCED_D::ZOOM_MID_LEVEL;
198+
float zoomMediumReach = ADVANCED_D::ZOOM_MEDIUM_REACH;
199199

200200
} advanced;
201201

source/source/game_state/gameplay/gameplay.cpp

+18-7
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,24 @@ void GameplayState::enter() {
262262
game.view.center.y = game.winH / 2.0f;
263263
game.view.updateTransformations();
264264

265+
float zoomReaches[3] = {
266+
game.config.rules.zoomClosestReach,
267+
game.options.advanced.zoomMediumReach,
268+
game.config.rules.zoomFarthestReach
269+
};
270+
float viewportReach = sqrt(game.view.size.x * game.view.size.y);
271+
for(int z = 0; z < 3; z++) {
272+
zoomLevels[z] = viewportReach / zoomReaches[z];
273+
}
274+
275+
if(curLeaderPtr) {
276+
game.view.cam.setPos(curLeaderPtr->pos);
277+
} else {
278+
game.view.cam.setPos(Point());
279+
}
280+
game.view.cam.setZoom(zoomLevels[1]);
281+
game.view.updateTransformations();
282+
265283
lastEnemyKilledPos = Point(LARGE_FLOAT);
266284
lastHurtLeaderPos = Point(LARGE_FLOAT);
267285
lastPikminBornPos = Point(LARGE_FLOAT);
@@ -921,13 +939,6 @@ void GameplayState::load() {
921939
changeToNextLeader(true, false, false);
922940
}
923941

924-
if(curLeaderPtr) {
925-
game.view.cam.setPos(curLeaderPtr->pos);
926-
} else {
927-
game.view.cam.setPos(Point());
928-
}
929-
game.view.cam.setZoom(game.options.advanced.zoomMidLevel);
930-
931942
//Memorize mobs required by the mission.
932943
if(game.curAreaData->type == AREA_TYPE_MISSION) {
933944
unordered_set<size_t> mission_required_mob_gen_idxs;

source/source/game_state/gameplay/gameplay.h

+3
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,9 @@ class GameplayState : public GameState {
380380
//Number of Pikmin lost so far, per type.
381381
map<PikminType*, long> pikminDeathsPerType;
382382

383+
//Closest, middle, and farthest zoom levels. Cache for convenience.
384+
float zoomLevels[3] = { 0.0f, 0.0f, 0.0f };
385+
383386

384387
//--- Function declarations ---
385388

0 commit comments

Comments
 (0)