From e150b701130ff54b6787ea0c59f5ed1c44ef6db1 Mon Sep 17 00:00:00 2001 From: Ritchie Cunningham Date: Mon, 7 Mar 2022 23:07:57 +0000 Subject: [PATCH] [Change] Refactored Animation [Add] Documentation Comments. --- .classpath | 1 + bin/tfg/AnimatedSprite.class | Bin 0 -> 3574 bytes bin/tfg/Direction.class | Bin 1009 -> 1009 bytes bin/tfg/Game.class | Bin 6235 -> 5567 bytes bin/tfg/Location.class | Bin 2708 -> 3346 bytes bin/tfg/Map.class | Bin 3682 -> 3673 bytes bin/tfg/Player.class | Bin 5538 -> 3381 bytes bin/tfg/TextUIElement.class | Bin 0 -> 2783 bytes bin/tfg/Tile.class | Bin 1943 -> 1949 bytes bin/tfg/UITextElement.class | Bin 2773 -> 0 bytes src/tfg/AnimatedSprite.java | 164 +++++++++++++++++++++++++++++++++ src/tfg/Direction.java | 4 + src/tfg/Game.java | 136 +++++++++++++++++----------- src/tfg/Location.java | 89 +++++++++++++++++- src/tfg/Map.java | 98 +++++++++++++++----- src/tfg/Player.java | 171 ++++++++++++++++------------------- src/tfg/PlayerAction.java | 2 +- src/tfg/TextUIElement.java | 88 ++++++++++++++++++ src/tfg/Tile.java | 38 ++++++-- src/tfg/UITextElement.java | 55 ----------- 20 files changed, 610 insertions(+), 236 deletions(-) create mode 100644 bin/tfg/AnimatedSprite.class create mode 100644 bin/tfg/TextUIElement.class delete mode 100644 bin/tfg/UITextElement.class create mode 100644 src/tfg/AnimatedSprite.java create mode 100644 src/tfg/TextUIElement.java delete mode 100644 src/tfg/UITextElement.java diff --git a/.classpath b/.classpath index d82323d..37d4dc5 100644 --- a/.classpath +++ b/.classpath @@ -7,5 +7,6 @@ + diff --git a/bin/tfg/AnimatedSprite.class b/bin/tfg/AnimatedSprite.class new file mode 100644 index 0000000000000000000000000000000000000000..c2cc4859d88cc2a190f8a71310a5e7894d755a31 GIT binary patch literal 3574 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 MH2P(A`nHw72J-awC;$Ke diff --git a/bin/tfg/Location.class b/bin/tfg/Location.class index 8832977d161e7ec8810874e22e2c31ae1cd5fb80..0e24d1acc5ca4417ad13b996bef96fc01a4640c2 100644 GIT binary patch delta 1023 zcmY+C-ES0C7{-5RnAz>l&X!W5ux-~SR7fdMgG8ye1sl6-b!8#6w5h?C(w)VHc6aG+ zOKXKHYJmztdXy0FxS@orDg+uZ#49gMQ2zq1xb#0Te!ORv3!UUW?|II7Kc4qF^UVv( z4el?0KYR>ybNPGss9hh;7b^Z#sW>rK@fFRjsdx3SRzpp$Gt4nXT>oxu-k)GN^Ku>QTQG^*co99Cp?-+m|foEB@!n7lt%{>ivCvpn-#ZmoyMu0equGY=Q^cM zx#asXwxHvWf8Pd1ycS&Qa>_32nDOZ4jGng}>*hS7crF{5_xOaf`j)+A&w|INxY9e>(?1ZAyYn8On*%3v z@bEyNIr-9KF$ft-_78-)sQC1GP&} zhPu>i`cA0Z>BeE7{v-5`layUbcZ4&}0X#DLX*i*8hj%+i1Puy$^2P|3Xy-956|=mE zPa}EW;uHs%;1C5qq{uN&GszSsDxBpE=b6>dYDO27+>Xf0tOvDIc!lJluRUUPI2wJx zSjKB9G%cR&u-8bp-J|tBnf5yp0fS;n%ob}FYZvPhdoRe{WY3uF6?Qy_Rg^GjlO0rE zVZERQfinSayHEB_#{|Tkd*l|)`q84~?ONmHs#IRbW?5gANinK(k$RS-=Vki1LYk|> z>1&2r78Nun_?9v^nBzO*lCiHk84aS2`L2l?1ynNF7Dh2UoC%1bnva#^=9~lW_H9_%5@n(zj0PHVNGX z+t@C?jXk_Bey_ay+v2NQRXMl;2TPcl5n71!g}L+(8&TrTa)I>!7oocp4D!{#9qGwq delta 534 zcmY+A-A)rx6otQO=da^YTd^obAfX9jO~inaU@-NE3bC;e+Sp(~{zOHER>8!?=!K8q z@d>=~wrHZp81%{uZ@lv%d$* zYg4haX=t=t>ZNKe;Gr%0D~_?R{UL8ZDGu15ej}5{6=(GHa)>+~_Ihx`>9jk+xRX=O z+GIHB_2SWIPluCUzbG#{Vr@9;4PZEKe}omUAUY}PvBgwt>=X%x2%Vgvn^7(> z#x>3{!#E3Ce2F3(a+_S@86{qD#STV`RadK*G+{y4bL!?bcxMg4>|pj^hA7#@g#fLl>3(FzTvj&A6eb~9F+@ix$~ZiKm7)`u8({6x#@bk zAuHIk=H9W~Qh>AuA5+L41~?%tXr;5#c%jSEBR_SUk^cwyc<*^0rbkZSqnMyp#hO5vI{f+SVvm9*fNZ^O7UY9{)4S zM^HH8JNN(;ifKp-3Qb(nL6s3I II_w+$1BHJ)YybcN delta 267 zcmWNLOG^S_6o#J<8f>%~5Czl5?iUm$#ImBI3s`icgiLT0B1po8Q{X~q5iO#1@@;~k zpAd9e`4fT`En3tjsDIEe=&a6jUe0-VKb;@vreIl(qqBUyQS+PiQ(xZ)lI_-j5s|Ri zzRei6KR}s z)0L~t^GEPf)usrDAVf}-Ga{a4ggMeIkY$k#nL8{~WQ7w}ITyYl&oyh@vCf0=6Pt9T xz#H3q3;&AekDOBMDw{pkOF?&fUd(+A@kBY$ElY>XvUx#*&as57wOfHh&IOO{(q_YEDe^MQ$a11)8*m_FbSkCoCz&l(?b@_u@cXC1VLO16Q9 zai!l~&KtO(TN>oj3Y@Z=F>sMS92obU!1hOMJILCHf{I7I<=y8n8=g{A)M^@7tSs+x zoiQu03)&u~68Vbf*>2EdjT4EI;gSc9;lZxFL}H*xo#{~Z9)%X>~|cV&3k z_6)43L1k46PB}eLuDAt#tQ;&Ry7FdF1 z2I8&BoQdTImYqKh3ACWO0R}D+Xh5O?m*O%Ls|b9iZaNr&)mT6;y?wo%QemyYd@L~0 zI;(nT1(d)#?VwFyA(~8VFtB6>PmO#6>$T+N0*kQN#1$-2ZLt&Bgv~Ox3#I?71We4G zi>t{A&-T;0m>b94qKRu~@oXUQ9JiRjR%|!1&A=i>L6?aic1m`--wH;2fgRY%lojp3 zK&G{OhNW6NbKBWlNxe18P(~(nw?GH>5Phj^74~}NvAy)eT83t4Dc*Lf&!k4wS{bju>oC-2>0Ah7bIS$nxB3VEs7_ zg*~PEB^f!hV{z@2P00-J7`HMQn6WfZ8|#*r;BzuR%`-pbgJ?Pc}o zXp(+PIm>h8d$?H_j5t2aQ`4|)DB}=+UHlz35VQHRMAvtA+GXeYYSxhV=gL+zI2u(^ zI4hLb1cThnsPZEmeYP4VqE!Kq(?lnsEYOGxh+vFP$V4SIuQeHovHiw4Ntk}Ey2tT2 zLFF7w=45wF2pj~FFQW23yTlPWVNWNTEq<2L>`F)r_X^wxwt!&vBkKt~fQL*xXuyrQeIEoicJa1ste@hFz zh?f}JK(?>Hzmsjd`v16)2wxF+RmM;!XAjF(kPMU=iZUnJ;@St94lXL=1>P(&__qY! z#ybWU4s(X{&MJg~yG1p%_sdGWC-6Q#U?muSWREH#9ilBxoGd;P_!ysX5^5j)W#7@4 z(pmK&PqH{Ja6$q%Eq&WDgaU6{1D&;v77c)Xwp)-LCBJHqa6Q$CyISX1xpZ1v=& zsrGppswb~HK27TLV&nf(z}P}tb=*Cgn!-h?pV2Zng%y*yICTmuC$WY*>$sDgM2gGx zTyC61n#)atEz75Hd&Cb|D z$!jT>q5M|P^KGzr!8+K9d$1cvcs)LcJ-D0Nn;9wt<@pewa+ODcp5)5rDn{)(45LV& z4nILg_#ejso;M-(H^Ic2I)lw;qN`3NahXmc+Er1Q+EhF~h0*V*5>v1fd;&M19yclo zLb)?T2nI?R3r%dNq?D~swN1i3)51PNA5a!9)KXCp^%!Th35wx*p{=xf2j(!H?#T#D zJ-31VH9+P>KzszD@^5qyr(BlGYe<6Q=;o@ut%^!dxHv5BuCL<$V^~g}JR*6bMdZm~ z6_205Qm)cfJar1s9Y;dHyez}g^-L+s4)MRpFR&3-)xlckdILt8%@Qj)#*Yq{LEoeB zuGE;Ku(Nm#uM_bi*7*&#K}^+Y9%6rDhlx#p@W8;Em@d#OVSzdbgh4%W92t%D*fA12 zq&jybncJ&)m%(agOIC8@!xJh7hW6=9469W89bycJ*;w~7hWm;CL0pZ8$i|1szDH|v z-4SA!e5yk%Bdfsy6lT4T0A6ei9tT6n@;<{10gAJIw$9 literal 5538 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 literal 0 HcmV?d00001 diff --git a/bin/tfg/Tile.class b/bin/tfg/Tile.class index 32013b13d8df15377337c64bdf12615afcde1981..9f22357db237ce5c0cff7557e85d9e5cec273d13 100644 GIT binary patch delta 533 zcmYk3PfrtJ7{q_?cG;!dl_E`yD3nwhNn2ux8iP<2{~$`SfFK1uZ3wYZQul9EuA4`oQ!?#et0#!PieZ;l$M}hc#d}AS#9<( zNS0yx7$wJ~lqvEoG9ZLgIKm}H@WcT%ZB=x8Om8XN-wgT`IyzD$xyEG)Cne;?@#B6X zw<~tA&9)#t)N+jdl3Zupes7zrU6nYZd4==xENEU*<_p|ph>8CaTs%tPXnsTLVS;3w zAa7jP$WmR{hSzT<>>IDQr^@tEnxam`d4eueJmCIUjD72M+n?U)V0QT%ZnJ*CgKfXu zm~E<@PP$de0=)`U5Er?`74czhUdt(Y{2_4-S$zG!#lK`Q;usdF9)qseTOBO1+~P<7 E0KNK4G5`Po delta 479 zcmYk2OG^S#6vzK}9A|PI98kkO0iUG~;2GhfxlND46_k|O8}w7!cL(MKo@ zf}};uh+6bvS{BtAk%$BT!#Vfd^Sl3htzBx$>-XamfC=o}DId%rM$Y*ss~E-nZmGae z1-EMv%QBW2ti}9EK3vL|_ruAv<4WOB#R{VQUO14}RK&2(J%(}nh6*!O1q_=i<}fcK z&5sN>tjOJB#;iafmV#-h{6f6l8+|}97OYaw057QrO{5x4SP_B^Bd}u(Em(wuU~NdF z13sE?)c0iROrlCb9OLAGVUj8{#4m(o_$?MQOqk+V#xBiWzox@Y1fSvW#zfppOMDdF z6g}`$1Q9?lf%_2thv{!%1nSQs(!iK>jE{*Tqm^WomnE;T5aMrAyOTOGtkPgJ0Rx0# z`YUZLP(z%*NP|iu_YAR`sUgWFIqXbS$-fota3Y0HdXArR00S6CiYMgOA>Ee?@{)|q X4}A%vtV;^fKOst%rUc}$RnObMHFHOR diff --git a/bin/tfg/UITextElement.class b/bin/tfg/UITextElement.class deleted file mode 100644 index ce9f62e6bb130702c676498c49fb615fc6f37f3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2773 zcmbVNTU!%X6kR7IOcF-Gct@!>E+Hsst+$HW0wxlTKuH8Cr8p!542DcP85HgPezCWI z;rI1PZ3VwxeC$JiRP8!vLJ$poD14bSXP)Ol%PY0hM5Bmv;nABayg~rG+q(_b6H@AC+tQYSe#oF{VPUERkDVwbgkKQ8pZ{7*QmA%J$L<84d`gveygTa;zDPV3l$>#X=_*CeYwiy0j`nN%I0=Upa{sHyR&Sww6_pOzU{?69xUS7e;dkCKi>N$ULiIOz@+mp;zjD z4HKRy=%ZXx-jJk00&hL9dlz+&si1aNlwH?-iU}pCyy+@%1(KF<9gp!2(Ttv-IpJR` ze=xb{bKhD{0&Z?95InmZuK9YXb*{7TZ*OtEE#J@KAnv;MxnfL{z`|P1+RWWy& z;Z7#vF1lGYr#PNQKN1|16n~UshSf98@j4|baP)+g*#;ttwoHr^?--f}HGKb6b_PfJ VxQolxN4om9ZX?PM-08!Q{{q^gY9{~y diff --git a/src/tfg/AnimatedSprite.java b/src/tfg/AnimatedSprite.java new file mode 100644 index 0000000..8fba2f4 --- /dev/null +++ b/src/tfg/AnimatedSprite.java @@ -0,0 +1,164 @@ +package tfg; + +import org.jsfml.graphics.IntRect; +import org.jsfml.graphics.Sprite; +import org.jsfml.system.Vector2f; +import org.jsfml.system.Vector2i; + +/** + * A sprite that supports animation. + * @author Ritchie Cunningham + */ +public class AnimatedSprite { + /** + * Speed of animation in Hz. + */ + private final float animationSpeed = 15; + /** + * The frame (stage) in the animation. + */ + private int animationFrame = 0; + /** + * Keeps track of time between frame changes. + */ + private int frameCounter = 0; + /** + * Whether or not the sprite is currently animated. + */ + private boolean animating = false; + /** + * The position at which the sprite is rendered. + */ + private Vector2f spritePosition = new Vector2f(0,0); + /** + * The sprite to animate. + */ + private Sprite animatedSprite; + /** + * Location of the entity this sprite represents. + */ + private Location entityLoc; + /** + * Size of the sprite. + */ + private final Vector2i spriteSize = new Vector2i(32, 48); + + /** + * Create a new animated sprite. + * @param s The sprite to animate. + * @param l The location of the entity the sprite represents. + */ + public AnimatedSprite(Sprite s, Location l) { + animatedSprite = s; + entityLoc = l; + } + + /** + * Start the animation. + */ + public void startWalkingAnimation() { + startAnimation(); + } + + /** + * Update animation. + */ + public void animate() { + if(animating) { /* Then update animation. */ + if(frameCounter >= animationSpeed) { /* If 15Hz has passed. */ + stopAnimation(); + } else { + /* Get the position between old and new. */ + spritePosition = entityLoc.interpolate(animationSpeed, frameCounter); + Vector2i entityPos = entityLoc.getPosition(); /* Get the entity position. */ + /* Subtract new position from starting position to get a number from 0.0 - 1.0. */ + Vector2f animationProgress = + Vector2f.sub(spritePosition, new Vector2f(entityPos.x,entityPos.y)); + /* Take the abs value because we're measuring distance. */ + float change = Math.abs(animationProgress.x+animationProgress.y); + /* Determine frame based on position. */ + if(change >= 0.f && change < .25f) { + animationFrame = 0; + } else if(change >= .25f && change < .5f) { + animationFrame = 1; + } else if(change >=.5f && change < .75f) { + animationFrame = 2; + } else if(change >= .75f && change <= 1.0f) { + animationFrame = 3; + } + } + frameCounter++; /* Increment on each update to keep track of time. */ + } + } + + /** + * Stop the animation. + */ + private void stopAnimation() { + /* Reset the following. */ + animating = false; + frameCounter = 0; + animationFrame = 0; + } + + /** + * Start the animation. + */ + private void startAnimation() { + animating = true; + } + + /** + * Determine whether or not the animation completed. + * @return If the animation finished. + */ + public boolean finishedAnimating() { + return !animating; + } + + /** + * Update the entity position. + * @param l The new location. + */ + public void updatePosition(Location l) { + entityLoc = l; /* Update the entity lcoation. */ + Vector2i entityPos = entityLoc.getPosition(); /* Get Pos from last location. */ + spritePosition = new Vector2f(entityPos.x, entityPos.y); /* Update sprite pos. */ + } + + /** + * Get the animated sprite to draw it. + * @return The anumated sprite. + */ + public Sprite getSprite() { + /* Set texture based on direction and animation frame. */ + animatedSprite.setTextureRect(getTextureCoords()); + /* Set sprite position */ + animatedSprite.setPosition(new Vector2f(spritePosition.x * spriteSize.x, + (spritePosition.y*spriteSize.x)-(spriteSize.y-spriteSize.x))); + return animatedSprite; + } + + private IntRect getTextureCoords() { + int topX = animationFrame * 32; /* x coord of the image. */ + int topY = 0; /* Top y coord of the image. */ + /* Match the correct image to the direction. */ + switch(entityLoc.getDirection()) { + case NORTH: + topY = 144; + break; + case SOUTH: + topY = 0; + break; + case EAST: + topY = 96; + break; + case WEST: + topY = 48; + break; + } + /* Create and return an int rectangle. */ + IntRect textureCoordsRect = new IntRect(topX, topY, spriteSize.x, spriteSize.y); + return textureCoordsRect; + } +} diff --git a/src/tfg/Direction.java b/src/tfg/Direction.java index 53a114d..422a9b0 100644 --- a/src/tfg/Direction.java +++ b/src/tfg/Direction.java @@ -1,3 +1,7 @@ package tfg; +/** + * The cardinal directions. + * @author Ritchie Cunningham + */ public enum Direction { NORTH, SOUTH, EAST, WEST }; diff --git a/src/tfg/Game.java b/src/tfg/Game.java index 78af144..42e5b15 100644 --- a/src/tfg/Game.java +++ b/src/tfg/Game.java @@ -1,7 +1,6 @@ package tfg; import org.jsfml.graphics.Color; -import org.jsfml.graphics.Font; import org.jsfml.graphics.RenderWindow; import org.jsfml.graphics.TextStyle; import org.jsfml.system.Clock; @@ -13,93 +12,117 @@ import org.jsfml.window.event.Event; /** * TFG Game's main class. + * This class ideally should be as short as possible. * @author Ritchie Cunningham */ public class Game { - private RenderWindow renderWindow = new RenderWindow(); - private final String renderWindowTitle = "TFG Game"; - private final Vector2i renderWindowDimensions = new Vector2i(640, 480); - private Player player; - private Camera camera; - private boolean renderWindowFocused = true; - private Font pixel = new Font(); - private int fps; - private static boolean limitFPS = false; - private UITextElement fpsCounter; + /** + * Main window where everything will be rendered to and handle input. + */ + private RenderWindow window = new RenderWindow(); + /** + * Set's the window title. + */ + private final String windowTitle = "TFG Game"; + /** + * Set dimensions (resolution) the window is created with. + */ + private final Vector2i windowDimensions = new Vector2i(640, 480); + /** + * Main object representing the player. + */ + private Player player = new Player(); + /** + * UI Element responsible for displaying the FPS. + */ + private final TextUIElement fpsUI = + new TextUIElement(InterfacePosition.TOP_LEFT, Color.YELLOW,24,TextStyle.BOLD); + + /** + * Repesents whether or not the user has the window opened and in focus. + */ + private boolean windowFocus = true; + + /** + * Create an instance of the game and run it. + * @param args Command line arguments passed in at run-time. + */ public static void main(String[] args) { Game g = new Game(); /* Create temp object of self. */ g.run(); /* Invoke run. */ } + /** + * Configure one-time settings at start-up. + */ public void handleInitialization() { - renderWindow.create(new VideoMode(renderWindowDimensions.x, - renderWindowDimensions.y), renderWindowTitle); - - fpsCounter = new UITextElement(InterfacePosition.TOP_LEFT, - Color.YELLOW,24,TextStyle.BOLD); - - if(limitFPS) { - renderWindow.setFramerateLimit(60); - } - - player = new Player(); - + window.create(new VideoMode(windowDimensions.x, windowDimensions.y), + windowTitle); player.changeMap(new Map(10, 10, Tile.SAND)); - camera = new Camera(renderWindow); } /** - * Run the game. + * Initializes the game and holds the main loop. */ public void run() { handleInitialization(); - int framesDrawn = 0; - float updateRate = 20.0f; /* 20hz */ - long maxUpdates = 1; - Clock updateClock = new Clock(); - Clock frameClock = new Clock(); - updateClock.restart(); + int framesDrawn = 0; /* Count each frame that is rendered */ + float updateRate = 20.0f; /* Limit the logic loop to update at 20hz */ + Clock updateClock = new Clock(); /* Clock used to restrict update loop rate */ + Clock frameClock = new Clock(); /* Used to calc average FPS. */ + updateClock.restart(); /* Reset update clock. */ + /* Calc next update time in millisecs. */ long nextUpdate = updateClock.getElapsedTime().asMilliseconds(); - while(renderWindow.isOpen()) { - long updates = 0; + /* As long as window is open, run main loop. */ + while(window.isOpen()) { handleInput(); + /* Make note of the current update time. */ long updateTime = updateClock.getElapsedTime().asMicroseconds(); - while ((updateTime-nextUpdate) >= updateRate && updates++ < maxUpdates) { + while ((updateTime-nextUpdate) >= updateRate) { handleLogic(); - nextUpdate += updateRate; + nextUpdate += updateRate; /* Compute next appropriate update time. */ } handleDrawing(); - framesDrawn++; + framesDrawn++; // Frame has rendered, increment. + /* How long has it been since last calulating FPS? */ float elapsedTime = frameClock.getElapsedTime().asSeconds(); - if(elapsedTime >= 1.0f) { - fps = (int)(framesDrawn/elapsedTime); - fpsCounter.updateString("FPS: " + fps); - framesDrawn = 0; - frameClock.restart(); + if(elapsedTime >= 1.0f) { /* If one second */ + /* Divide the frames rendered by one second. */ + fpsUI.updateString("FPS: " + (int) (framesDrawn/elapsedTime)); + framesDrawn = 0; /* Reset the count. */ + frameClock.restart(); /* Reset the frame clock. */ } } } public void handleInput() { - for(Event event : renderWindow.pollEvents()) { + /* + * Window based event queue. + * Good for single-press actions, not for repeated actions though. + */ + for(Event event : window.pollEvents()) { switch(event.type) { case CLOSED: - renderWindow.close(); + window.close(); break; case GAINED_FOCUS: - renderWindowFocused = true; + windowFocus = true; break; case LOST_FOCUS: - renderWindowFocused = false; + windowFocus = false; default: break; } } - if(renderWindowFocused) { + /* + * Real-time input. + * Good for repeated actions, bad for single-press actions. + */ + if(windowFocus) { if(Keyboard.isKeyPressed(Key.W)) { player.move(Direction.NORTH); } else if(Keyboard.isKeyPressed(Key.S)) { @@ -109,22 +132,29 @@ public class Game { } else if(Keyboard.isKeyPressed(Key.D)) { player.move(Direction.EAST); } else if(Keyboard.isKeyPressed(Key.ESCAPE)) { - renderWindow.close(); + window.close(); } } } + /** + * Update at a fixed rate (20Hz). + */ public void handleLogic() { player.update(); - Camera.MoveTo(player.getPosition(), 0.5f); } + /** + * Updates as fast as possible. Draws all objects onto the screen. + */ public void handleDrawing() { - renderWindow.clear(); - renderWindow.draw(player.getMap()); - renderWindow.draw(player); - renderWindow.draw(fpsCounter); - renderWindow.display(); + /* The window has automatic double-buffering. */ + window.clear(); + /* Draw each object like layers, background to foreground. */ + window.draw(player.getMap()); + window.draw(player); + window.draw(fpsUI); + window.display(); } } \ No newline at end of file diff --git a/src/tfg/Location.java b/src/tfg/Location.java index 0249f42..3b8abef 100644 --- a/src/tfg/Location.java +++ b/src/tfg/Location.java @@ -1,4 +1,6 @@ package tfg; + +import org.jsfml.system.Vector2f; import org.jsfml.system.Vector2i; /** @@ -6,52 +8,100 @@ import org.jsfml.system.Vector2i; * @author Ritchie Cunningham */ public class Location implements Cloneable { + /** + * Vector position (x,y). + */ private Vector2i locPosition = new Vector2i(0,0); + /** + * Cardinal direction (N,S,E,W). + */ private Direction locDirection; + /** + * Create a new location at x, y facing south. + * @param x New x-coorindate. + * @param y New y-coordinate. + */ public Location(int x, int y) { this(x, y, Direction.SOUTH); } + /** + * Create a new location at x, y with with specified direction. + * @param x New x-coordinate. + * @param y New y-coordinate. + * @param d New direction. + */ public Location(int x, int y, Direction d) { locPosition = new Vector2i(x,y); locDirection = d; } + /** + * Get position. + * @return Integer vector of position. + */ public Vector2i getPosition() { return locPosition; } + /** + * Get the direction. + * @return The direction. + */ public Direction getDirection() { return locDirection; } + /** + * Set the position. + * @param newPosition the new position vector. + */ public void setPosition(Vector2i newPosition) { locPosition = newPosition; } - + + /** + * Set the direction. + * @param newDirection The new direction. + */ public void setDirection(Direction newDirection) { locDirection = newDirection; } + /** + * Add another position with the current position. + * @param position The position to add with the current position. + */ public void addPosition(Vector2i position) { locPosition = Vector2i.add(locPosition, position); } + /** + * Subtract another position from the current position. + * @param position The position to subtract from the current position. + */ public void subtractPosition(Vector2i position) { locPosition = Vector2i.sub(locPosition, position); } + /** + * Get the location in the direction from the current position. + * @param d The relative direction. + * @return The position in the relative direction. + */ Location getRelativeLocation(Direction d) { Location thisLocation = this; Location newLocation = new Location(0,0); + /* Copy the current location. */ try { newLocation = thisLocation.clone(); } catch(CloneNotSupportedException ex) { ex.printStackTrace(); } + /* Modify the new location based on the direction. */ switch(d) { case NORTH: newLocation.subtractPosition(new Vector2i(0,1)); @@ -70,6 +120,43 @@ public class Location implements Cloneable { return newLocation; } + + /** + * Return a position in-between two locations. + * @param speed Size of the step. + * @param step Current step. + * @return Vector position in-between two locations. + */ + public Vector2f interpolate(float speed, int step) { + Vector2f interpolateAddition = new Vector2f(0,0); /* Init new vector. */ + /* + * 1.0f / speed calculated the step increments + * Multiplying it by step calculates the current increment. + */ + float additionAmount = (1.0f/speed)*step; /* Current increment. */ + /* Apply the increment to the vector based on the direction. */ + switch(locDirection) { + case NORTH: + interpolateAddition = new Vector2f(0, -additionAmount); + break; + case SOUTH: + interpolateAddition = new Vector2f(0, additionAmount); + break; + case EAST: + interpolateAddition = new Vector2f(additionAmount, 0); + break; + case WEST: + interpolateAddition = new Vector2f(-additionAmount, 0); + break; + } + Vector2i currentPos = getPosition(); + /* Add the increment to the base vector */ + return Vector2f.add(new Vector2f(currentPos.x, currentPos.y), interpolateAddition); + } + + /** + * Allows location to be copied. + */ protected Location clone() throws CloneNotSupportedException { return (Location) super.clone(); } diff --git a/src/tfg/Map.java b/src/tfg/Map.java index 0e5a37b..b9d1a11 100644 --- a/src/tfg/Map.java +++ b/src/tfg/Map.java @@ -20,76 +20,128 @@ import java.util.Arrays; * @author Ritchie Cunningham */ public class Map implements Drawable { - private Vector2i mapDimensions = new Vector2i(0, 0); + /** + * The size (length, width) of the map. + */ + private Vector2i dimensions = new Vector2i(0, 0); private Tile[][] tileArray; - private Texture mapTilesheetTexture = new Texture(); - private VertexArray mapVertexArray = new VertexArray(); + /** + * The tilesheet texture. + */ + private Texture tilesheetTexture = new Texture(); + /** + * Vertex array for the tile map. + * This is a streamlined way to draw many sprites at once. + */ + private VertexArray vertexArray = new VertexArray(); + /** + * Create a new map of specified size and tile type. + * @param l Map length. + * @param w Map width. + * @param t Default tile to auto-pupulate map. + */ public Map(int l, int w, Tile t) { - mapDimensions = new Vector2i(l,w); - tileArray = new Tile[mapDimensions.x][mapDimensions.y]; + dimensions = new Vector2i(l,w); + tileArray = new Tile[dimensions.x][dimensions.y]; try { - mapTilesheetTexture.loadFromFile(Paths.get("res/terrain.png")); + tilesheetTexture.loadFromFile(Paths.get("res/terrain.png")); } catch(IOException ex) { ex.printStackTrace(); } - mapVertexArray.setPrimitiveType(PrimitiveType.QUADS); - initializeMap(t); + /* Set vertex array to use quads because the tiles are square. */ + vertexArray.setPrimitiveType(PrimitiveType.QUADS); + initializeMap(t); /* Auto-populate the map with specified tile. */ } + /** + * Create a new map of speceified size that default to grass. + * @param l Map length. + * @param w Map width. + */ public Map(int l, int w) { this(l,w,Tile.GRASS); } + /** + * Fill the entire map to the specified tile. + * @param initialTile The tile to populate the map with. + */ public void initializeMap(Tile initialTile) { + /** + * Arrays.fill does not work with matrices, + * therefore we have to loop through the outer level to fill the inner. + */ for(Tile[] row : tileArray) { + /* Set each tile in the row to the specified tile. */ Arrays.fill(row,initialTile); } } + /** + * Draw the map onto the window. + */ public void draw(RenderTarget target, RenderStates states) { - mapVertexArray.clear(); + vertexArray.clear(); /* empty array from previous draw. */ final int tileSize = Tile.getSize(); - for(int i = 0; i < mapDimensions.x; i++) { - for(int j = 0; j < mapDimensions.y; j++) { - Tile tileType = tileArray[i][j]; + /* Iterate through every tile in the map. */ + for(int i = 0; i < dimensions.x; i++) { + for(int j = 0; j < dimensions.y; j++) { + Tile tileType = tileArray[i][j]; /* Grab current tile in the loop. */ + /* Grab texture coord to render the tile. */ Vector2f textureCoords = Tile.getTextureCoords(tileType); + /* + * Add each corner of the tile to the vertex array + * counter-clockwise. + */ /* Top left. */ - mapVertexArray.add(new Vertex( + vertexArray.add(new Vertex( new Vector2f(i*tileSize, j* tileSize), textureCoords)); /* Bottom left. */ - mapVertexArray.add(new Vertex( + vertexArray.add(new Vertex( new Vector2f(i*tileSize,(j*tileSize)+tileSize), Vector2f.add(textureCoords, new Vector2f(tileSize,tileSize)))); /* Bottom right. */ - mapVertexArray.add(new Vertex( + vertexArray.add(new Vertex( new Vector2f((i*tileSize)+tileSize, (j*tileSize)+tileSize), Vector2f.add(textureCoords, new Vector2f(tileSize,tileSize)))); /* Top right. */ - mapVertexArray.add(new Vertex( + vertexArray.add(new Vertex( new Vector2f((i*tileSize)+tileSize, j*tileSize), Vector2f.add(textureCoords, new Vector2f(tileSize,0)))); } } - RenderStates newStates = new RenderStates(mapTilesheetTexture); - mapVertexArray.draw(target, newStates); + /* Apply texture to the vertex array. */ + RenderStates newStates = new RenderStates(tilesheetTexture); + vertexArray.draw(target, newStates); /* Draw vertex array. */ } + /** + * Return the tile at specified location. + * @param l Location of the tile to get. + * @return Tile at the specified location. + */ public Tile getTile(Location l) { - Vector2i position = l.getPosition(); - Tile t = tileArray[position.x][position.y]; + Vector2i position = l.getPosition(); /* Get pos from loc. */ + Tile t = tileArray[position.x][position.y]; /* Get tile at this pos. */ return t; } + /** + * Determine whether or not the location fits within the map. + * @param l Location to test. + * @return If location is valid. + */ public boolean isValidLocation(Location l) { - Vector2i coordinates = l.getPosition(); + Vector2i coordinates = l.getPosition(); /* Pos from last location. */ + /* Return true if the location is greater than 0. */ return ((coordinates.x >= 0) && (coordinates.y >=0) && - (coordinates.x < mapDimensions.x) && - (coordinates.y < mapDimensions.y) && Tile.getCanWalkOn(getTile(l))); + (coordinates.x < dimensions.x) && + (coordinates.y < dimensions.y) && Tile.getCanWalkOn(getTile(l))); } } diff --git a/src/tfg/Player.java b/src/tfg/Player.java index 6865f91..6aff622 100644 --- a/src/tfg/Player.java +++ b/src/tfg/Player.java @@ -4,156 +4,137 @@ import org.jsfml.audio.Sound; import org.jsfml.audio.SoundBuffer; import org.jsfml.audio.SoundSource; import org.jsfml.graphics.Drawable; -import org.jsfml.graphics.IntRect; import org.jsfml.graphics.RenderStates; import org.jsfml.graphics.RenderTarget; import org.jsfml.graphics.Sprite; import org.jsfml.graphics.Texture; -import org.jsfml.system.Vector2f; -import org.jsfml.system.Vector2i; import java.io.IOException; import java.nio.file.Paths; /** - * Player Class + * Holds everything that pertains to the player (you?). * @author Ritchie Cunningham */ public class Player implements Drawable { + /** + * The players location. + */ private Location playerLoc; + /** + * The texture for the sprite. + */ private Texture playerSpritesheetTexture = new Texture(); - private Sprite playerSprite = new Sprite(); + /** + * The player sprite that supports animation. + */ + private final AnimatedSprite playerSprite; + /** + * The map the player is currently on. + */ private Map currentMap; - private final Vector2i playerSize = new Vector2i(32, 48); + /** + * The action the player is currently performing. + */ private PlayerAction currentAction = PlayerAction.NONE; - private Location newPlayerLoc; - private int frameCounter = 0; - private final float animationSpeed = 15.f; - private int animationFrame = 0; - private SoundBuffer cannotMoveBuffer = new SoundBuffer(); - private Sound cannotMove = new Sound(); - private Vector2f tempPosition = new Vector2f(0,0); /* Horrible Hack. */ + /** + * The buffer that allows the 'stuck' sound to be loaded. + */ + private final SoundBuffer cannotMoveBuffer = new SoundBuffer(); + /** + * The object that plays the 'stuck' sound. + */ + private final Sound cannotMove = new Sound(); - public Player() { - playerLoc = new Location(0, 0); + /** + * Create a new player with a location at (x,y). + * @param x Starting x pos. + * @param y Starting y pos. + */ + public Player(int x, int y) { + playerLoc = new Location(x, y); + /* Load sprite texture and 'stuck' sound. */ try { playerSpritesheetTexture.loadFromFile(Paths.get("res/player.png")); cannotMoveBuffer.loadFromFile(Paths.get("res/stuck.wav")); } catch(IOException ex) { ex.printStackTrace(); } - playerSprite = new Sprite(playerSpritesheetTexture); + Sprite sprite = new Sprite(); /* Create a new regular sprite. */ + sprite.setTexture(playerSpritesheetTexture); + /* Create a new animated sprite from the regular sprite. */ + playerSprite = new AnimatedSprite(sprite, playerLoc); cannotMove.setBuffer(cannotMoveBuffer); } + /** + * Create a new player at(0,0). + */ + public Player() { + this(0,0); + } + + /** + * Change the map the is on. + * @param m New map. + */ public void changeMap(Map m) { currentMap = m; } + /** + * Get the map the player is currently on. + * @return Map player is currently on. + */ public Map getMap() { return currentMap; } + /** + * Move the player in the specified direction. + * @param d Direction to move the player. + */ public void move(Direction d) { if(currentAction == PlayerAction.NONE) { + /* + * Get the location relative to the current location. + * e.g. NORTH would return the location above the current location. + */ Location newLoc = playerLoc.getRelativeLocation(d); playerLoc.setDirection(d); if(currentMap.isValidLocation(newLoc)) { currentAction = PlayerAction.MOVING; - newPlayerLoc = newLoc; + playerLoc.setDirection(d); + playerSprite.startWalkingAnimation(); } else if(cannotMove.getStatus() == SoundSource.Status.STOPPED) { cannotMove.play(); } } } - public void resetLocation() { - playerLoc = new Location(0, 0); - } - - public Vector2f getPosition() { - return playerSprite.getPosition(); - } - - public IntRect getTextureCoords() { - IntRect textureCoordsRect = new IntRect(0,0,0,0); - - switch(playerLoc.getDirection()) { - case NORTH: - textureCoordsRect = - new IntRect(0+(animationFrame*32), 144, playerSize.x, playerSize.y); - break; - case SOUTH: - textureCoordsRect = - new IntRect(0+(animationFrame*32),0,playerSize.x,playerSize.y); - break; - case EAST: - textureCoordsRect = - new IntRect(0+(animationFrame*32),96,playerSize.x,playerSize.y); - break; - case WEST: - textureCoordsRect = - new IntRect(0+(animationFrame*32),48,playerSize.x,playerSize.y); - break; - } - return textureCoordsRect; - } + /** + * Update the animation progress. + */ public void update() { - /* Dirty dirty hack and should be fixed asap. */ - tempPosition = new Vector2f(0,0); - Vector2i currentPlayerPosition = playerLoc.getPosition(); if(currentAction == PlayerAction.MOVING) { - if(frameCounter >= animationSpeed) { - frameCounter = 0; + if(playerSprite.finishedAnimating()) { currentAction = PlayerAction.NONE; - playerLoc = newPlayerLoc; - newPlayerLoc = null; - Vector2i newPlayerPosition = playerLoc.getPosition(); - tempPosition = new Vector2f(newPlayerPosition.x, newPlayerPosition.y); - animationFrame = 0; + /* Actually move the location. */ + playerLoc = playerLoc.getRelativeLocation(playerLoc.getDirection()); + /* Update the sprite with new location. */ + playerSprite.updatePosition(playerLoc); } else { - float additionX = 0.0f; - float additionY = 0.0f; - switch(playerLoc.getDirection()) { - case NORTH: - additionY = -(1.0f / animationSpeed) * (frameCounter); - break; - case SOUTH: - additionY = (1.0f / animationSpeed) * (frameCounter); - case EAST: - additionX = (1.0f / animationSpeed) * (frameCounter); - break; - case WEST: - additionX = -(1.0f / animationSpeed) * (frameCounter); - break; - } - float change = Math.abs(additionX + additionY); - if(change >= 0.f && change < .25f) { - animationFrame = 0; - } else if(change >= .25f && change < .5f) { - animationFrame = 1; - } else if(change >= .5f && change < .75f) { - animationFrame = 2; - } else if(change >= .75f && change <= 1.0f) { - animationFrame = 3; - } - tempPosition = new Vector2f(currentPlayerPosition.x + additionX, - currentPlayerPosition.y + additionY); + playerSprite.animate(); /* Proceed with the animation. */ } - frameCounter++; - } else { - tempPosition = new Vector2f(currentPlayerPosition.x, currentPlayerPosition.y); } } + /** + * Draw the player on screen. + */ public void draw(RenderTarget target, RenderStates states) { - playerSprite.setPosition( - new Vector2f(tempPosition.x*playerSize.x, - (tempPosition.y*playerSize.x)-(playerSize.y-playerSize.x))); - - playerSprite.setTextureRect(getTextureCoords()); - RenderStates newStates = new RenderStates(playerSpritesheetTexture); - playerSprite.draw(target, newStates); + /* Get the animated sprite and draw it. */ + playerSprite.getSprite().draw(target, states); } } diff --git a/src/tfg/PlayerAction.java b/src/tfg/PlayerAction.java index 3628952..12b72da 100644 --- a/src/tfg/PlayerAction.java +++ b/src/tfg/PlayerAction.java @@ -1,7 +1,7 @@ package tfg; /** - * Actions the player can carry out. + * Potential actions the player can carry out. * @author Ritchie Cunningham */ public enum PlayerAction {NONE, MOVING } diff --git a/src/tfg/TextUIElement.java b/src/tfg/TextUIElement.java new file mode 100644 index 0000000..61099b8 --- /dev/null +++ b/src/tfg/TextUIElement.java @@ -0,0 +1,88 @@ +package tfg; + +import org.jsfml.graphics.Color; +import org.jsfml.graphics.Drawable; +import org.jsfml.graphics.Font; +import org.jsfml.graphics.RenderStates; +import org.jsfml.graphics.RenderTarget; +import org.jsfml.graphics.Text; +import org.jsfml.graphics.TextStyle; + +import java.io.IOException; +import java.nio.file.Paths; + +/** + * UI Elements containing a dynamic text label. + * @author Ritchie Cunningham + */ +public class TextUIElement implements Drawable { + /** + * The font for the text. + */ + private Font font = new Font(); + /** + * The text object containing style and content. + */ + private Text text = new Text(); + + /** + * Create a new Text UI Element with the specified options and a default style. + * @param p Position on the screen to display the label. + * @param c The Color to set the text. + * @param size The size to render the text. + */ + public TextUIElement(InterfacePosition p, Color c, int size) { + this(p, c, size, TextStyle.REGULAR); + } + + /** + * Create a new Text UI element with the specified options and style. + * @param p Position on the screen to display the label. + * @param c Color to set the text. + * @param size Size to render the text. + * @param style Style to apply to the text. + */ + public TextUIElement(InterfacePosition p, Color c, int size, int style) { + /* Attempt to load font. */ + try { + font.loadFromFile(Paths.get("res/kpixel.ttf")); + } catch (IOException ex) { + ex.printStackTrace(); + } + + text.setFont(font); /* Apply the selected font. */ + text.setCharacterSize(size); /* Update the character size. */ + text.setColor(c); /* Change the color. */ + text.setStyle(style); /* Set the desired style. */ + setPosition(p); /* Position the label. */ + } + + /** + * Update the value of the text. + * @param s New value for the text. + */ + public void updateString(String s) { + text.setString(s); + } + + /** + * Position the element on the screen. + * @param p Position on screen. + */ + public void setPosition(InterfacePosition p) { + switch(p) { + case TOP_LEFT: + text.setPosition(0,0); /* Default (0,0) if pos is top left. */ + break; + default: + break; + } + } + + /** + * Draw the UI elements to screen. + */ + public void draw(RenderTarget target, RenderStates states) { + text.draw(target, states); + } +} diff --git a/src/tfg/Tile.java b/src/tfg/Tile.java index b73455d..b77964a 100644 --- a/src/tfg/Tile.java +++ b/src/tfg/Tile.java @@ -3,14 +3,26 @@ package tfg; import org.jsfml.system.Vector2f; /** - * Map tiles for the Map class. + * Enumeration of tiles comprising maps. * @author Ritchie Cunningham */ public enum Tile { - WATER, SAND, GRASS; + WATER, /* Wet and wild tile. */ + SAND, /* Urgh, it gets between my toes. */ + GRASS; /* Soft, green, vivid, inviting.. */ + /** + * Length or width of a map tile. + * Each tile *MUST* be a square, therefore the area of + * the tile is this number squared. + */ private static int tileSize = 32; + /** + * Get the coords of a specific tile from the tile-set image. + * @param t The tole to get the coordinates of. + * @return Coords of the tile image in the tile-set. + */ public static Vector2f getTextureCoords(Tile t) { Vector2f textureCoordinates = new Vector2f(0, 0); switch(t) { @@ -21,29 +33,39 @@ public enum Tile { textureCoordinates = new Vector2f(576, 352); break; case GRASS: - textureCoordinates = new Vector2f(448, 252); + textureCoordinates = new Vector2f(448, 352); break; } return textureCoordinates; } + /** + * Get the side length of a square tile. + * The tile area is tileSize^2. + * @return Length of a square map tile. + */ public static int getSize() { return tileSize; } + /** + * Determine if this tile is safe for the player to walk on. + * @param t Tile to test. + * @return If the player can walk on it. + */ public static boolean getCanWalkOn(Tile t) { - boolean able = false; + boolean canWalk = false; switch(t) { case WATER: - able = false; + canWalk = false; break; case SAND: - able = true; + canWalk = true; break; case GRASS: - able = true; + canWalk = true; break; } - return able; + return canWalk; } } diff --git a/src/tfg/UITextElement.java b/src/tfg/UITextElement.java deleted file mode 100644 index 509ee00..0000000 --- a/src/tfg/UITextElement.java +++ /dev/null @@ -1,55 +0,0 @@ -package tfg; - -import org.jsfml.graphics.Color; -import org.jsfml.graphics.Drawable; -import org.jsfml.graphics.Font; -import org.jsfml.graphics.RenderStates; -import org.jsfml.graphics.RenderTarget; -import org.jsfml.graphics.Text; -import org.jsfml.graphics.TextStyle; - -import java.io.IOException; -import java.nio.file.Paths; - -/** - * GUI Elements - * @author Ritchie Cunningham - */ -public class UITextElement implements Drawable { - private Font font = new Font(); - private Text text = new Text(); - private String value; - - public UITextElement(InterfacePosition p, Color c, int size) { - this(p, c, size, TextStyle.REGULAR); - } - - public UITextElement(InterfacePosition p, Color c, int size, int style) { - try { - font.loadFromFile(Paths.get("res/kpixel.ttf")); - } catch (IOException ex) { - ex.printStackTrace(); - } - - text = new Text("", font, size); - text.setColor(c); - text.setStyle(style); - setPosition(p); - } - - public void updateString(String s) { - text.setString(s); - } - - public void setPosition(InterfacePosition p) { - switch(p) { - case TOP_LEFT: - text.setPosition(0,0); - break; - } - } - - public void draw(RenderTarget target, RenderStates states) { - text.draw(target, states); - } -}