From 3b9d7941638176961d469f8e33b5f2ee90e2e9ab Mon Sep 17 00:00:00 2001 From: wangsj <3305688534@qq.com> Date: Sun, 21 Sep 2025 21:48:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E4=BA=BA=E7=89=A9=E7=88=B6?= =?UTF-8?q?=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/uno/mloluyu/characters/Fighter.java | 2 +- .../java/uno/mloluyu/desktop/GameCore.java | 14 +- .../uno/mloluyu/desktop/character/Alice.java | 216 ++++-------------- .../mloluyu/characters/Fighter$Action.class | Bin 1672 -> 1724 bytes .../uno/mloluyu/characters/Fighter.class | Bin 8530 -> 8581 bytes .../uno/mloluyu/desktop/GameCore.class | Bin 1458 -> 1704 bytes .../uno/mloluyu/desktop/character/Alice.class | Bin 6439 -> 1902 bytes 7 files changed, 57 insertions(+), 175 deletions(-) diff --git a/src/main/java/uno/mloluyu/characters/Fighter.java b/src/main/java/uno/mloluyu/characters/Fighter.java index 9cc7e6b..06d9a86 100644 --- a/src/main/java/uno/mloluyu/characters/Fighter.java +++ b/src/main/java/uno/mloluyu/characters/Fighter.java @@ -15,7 +15,7 @@ public abstract class Fighter implements Disposable { // 动作类型枚举 - 所有角色共用的基础动作 public enum Action { IDLE, WALK, JUMP, FALL, - ATTACK1, ATTACK2, ATTACK3, + ATTACK1, ATTACK2, ATTACK3,ATTACK4, HIT, DEFEND, SPECIAL1, SPECIAL2, DEATH diff --git a/src/main/java/uno/mloluyu/desktop/GameCore.java b/src/main/java/uno/mloluyu/desktop/GameCore.java index ce02cd9..e6c73ef 100644 --- a/src/main/java/uno/mloluyu/desktop/GameCore.java +++ b/src/main/java/uno/mloluyu/desktop/GameCore.java @@ -5,18 +5,20 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; import uno.mloluyu.desktop.character.Alice; public class GameCore implements ApplicationListener { private SpriteBatch batch; - private Texture img; - private Alice alice1 = new Alice(); + private TextureAtlas atlas; + private Alice alice1; + @Override public void create() { - alice1.create(); - + atlas = new TextureAtlas(Gdx.files.internal("characters/alice.atlas")); + alice1= new Alice(); } @@ -25,8 +27,10 @@ public class GameCore implements ApplicationListener { Gdx.gl.glClearColor(150, 150, 150, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); + alice1.update(Gdx.graphics.getDeltaTime()); - alice1.render(); + batch.begin(); + alice1.render(batch); } @Override diff --git a/src/main/java/uno/mloluyu/desktop/character/Alice.java b/src/main/java/uno/mloluyu/desktop/character/Alice.java index a88613c..05cce69 100644 --- a/src/main/java/uno/mloluyu/desktop/character/Alice.java +++ b/src/main/java/uno/mloluyu/desktop/character/Alice.java @@ -1,179 +1,57 @@ package uno.mloluyu.desktop.character; +import uno.mloluyu.characters.Fighter; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import uno.mloluyu.util.SimpleFormatter; +/** + * 角色类,继承自Fighter父类 + */ +public class Alice extends Fighter { -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.Input; -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.g2d.Animation; -import com.badlogic.gdx.graphics.g2d.SpriteBatch; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.Array; - -public class Alice { - private SpriteBatch batch; - private Animation walkAnimation; // 行走动画 - private Animation idleAnimation; // idle动画 - private TextureRegion currentFrame; // 当前显示的帧 - private float stateTime; // 动画播放时间 - - private String path = "character/alice/"; - private final float MOVEMENT_SPEED = 200f; - private Vector2 position; - private float width; // 角色宽度 - private float height; // 角色高度 - private boolean isMoving = false; // 是否在移动 - private boolean isFacingRight = true; // 是否面朝右 - - public void create() { - batch = new SpriteBatch(); - position = new Vector2(); - - // 加载动画帧 - loadAnimations(); - - // 初始化位置(屏幕中心) - setToCenter(); + public Alice(TextureAtlas atlas) { + super(atlas); + speed = 350f; // 速度更快 + maxHealth = 90; // 生命值较低 + health = maxHealth; + attackPower = 12; // 攻击力中等 } + + @Override + protected void loadAnimations() { + loadAnimationFromAtlas(Action.IDLE, "stand", 15, true); + loadAnimationFromAtlas(Action.WALK, "walkFront", 9, true); + loadAnimationFromAtlas(Action.JUMP, "jump", 8, false); + loadAnimationFromAtlas(Action.FALL, "hitSpin", 5, false); + loadAnimationFromAtlas(Action.ATTACK1, "attackAa", 6, false); + loadAnimationFromAtlas(Action.ATTACK2, "attackAb", 6, false); + loadAnimationFromAtlas(Action.ATTACK3, "attackAc", 6, false); + loadAnimationFromAtlas(Action.ATTACK4, "attackAd", 6, false); - /** - * 加载动画帧序列 - */ - private void loadAnimations() { - try { - // 1. 加载静止动画 - Array idleFrames = new Array<>(); - for (int i = 0; i < 16; i++) { - Texture texture = new Texture(Gdx.files.internal(path + "stand" + SimpleFormatter.addLeadingZeros(i,3) + ".png")); //文件路径 - System.out.println(texture); - idleFrames.add(new TextureRegion(texture)); - } - - idleAnimation = new Animation<>(0.1f, idleFrames, Animation.PlayMode.LOOP); // 每帧时间 - - // 2. 加载行走动画 - Array walkFrames = new Array<>(); - for (int i = 0; i < 5; i++) { - Texture texture = new Texture(Gdx.files.internal(path + "walkFront" + SimpleFormatter.addLeadingZeros(i,3) + ".png")); - System.out.println("调试代码"+texture); - walkFrames.add(new TextureRegion(texture)); - } - walkAnimation = new Animation<>(0.1f, walkFrames, Animation.PlayMode.LOOP); - - // 设置角色尺寸 - width = idleFrames.get(0).getRegionWidth(); - height = idleFrames.get(0).getRegionHeight(); - - Gdx.app.log("Alice", "动画加载成功"); - - } catch (Exception e) { - Gdx.app.error("Alice", "动画加载失败: " + e.getMessage()); - e.printStackTrace(); - } + loadAnimationFromAtlas(Action.HIT, "hitSpin", 5, false); + + // 为忍者特定动作设置帧间隔 + setFrameDuration(Action.WALK, 0.08f); // 行走更快 + setFrameDuration(Action.ATTACK1, 0.07f); // 攻击更快 + setFrameDuration(Action.SPECIAL2, 0.06f); // 特殊技能2非常快 } - - /** - * 设置角色到屏幕中心 - */ - private void setToCenter() { - float x = (Gdx.graphics.getWidth() - width) / 2f; - float y = (Gdx.graphics.getHeight() - height) / 2f; - position.set(x, y); - } - - /** - * 更新逻辑和动画 - */ - public void update(float deltaTime) { - if (idleAnimation == null) return; - - stateTime += deltaTime; - - handleMovement(deltaTime); - - if (isMoving) { - currentFrame = walkAnimation.getKeyFrame(stateTime); - } else { - currentFrame = idleAnimation.getKeyFrame(stateTime); - } - - if ((isFacingRight && currentFrame.isFlipX()) || - (!isFacingRight && !currentFrame.isFlipX())) { - currentFrame.flip(true, false); - } - } - - /** - * 处理移动逻辑 - */ - private void handleMovement(float deltaTime) { - float moveX = 0; - float moveY = 0; - isMoving = false; - - // 方向键控制 - if (Gdx.input.isKeyPressed(Input.Keys.UP)) { - moveY += MOVEMENT_SPEED * deltaTime; - isMoving = true; - } - if (Gdx.input.isKeyPressed(Input.Keys.DOWN)) { - moveY -= MOVEMENT_SPEED * deltaTime; - isMoving = true; - } - if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) { - moveX += MOVEMENT_SPEED * deltaTime; - isMoving = true; - isFacingRight = true; // 朝右 - } - if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) { - moveX -= MOVEMENT_SPEED * deltaTime; - isMoving = true; - isFacingRight = false; // 朝左 - } - - // 更新位置并限制在屏幕内 - position.add(moveX, moveY); - clampPosition(); - } - - /** - * 限制在屏幕范围内 - */ - private void clampPosition() { - float maxX = Gdx.graphics.getWidth() - width; - float maxY = Gdx.graphics.getHeight() - height; - position.x = Math.max(0, Math.min(position.x, maxX)); - position.y = Math.max(0, Math.min(position.y, maxY)); - } - - /** - * 渲染角色和动画 - */ - public void render() { - if (batch == null || currentFrame == null) return; - batch.begin(); - batch.draw(currentFrame, position.x, position.y); - batch.end(); - } - - /** - * 释放资源 - */ - public void dispose() { - if (batch != null) { - batch.dispose(); - batch = null; - } - if (idleAnimation != null) { - for (TextureRegion region : idleAnimation.getKeyFrames()) { - region.getTexture().dispose(); - } - } - if (walkAnimation != null) { - for (TextureRegion region : walkAnimation.getKeyFrames()) { - region.getTexture().dispose(); + + // 忍者特定的移动状态处理 + @Override + protected void handleMoveState() { + // 忍者在跳跃时也能移动 + if (currentAction != Action.ATTACK1 && currentAction != Action.ATTACK2 && + currentAction != Action.ATTACK3 && currentAction != Action.SPECIAL1 && + currentAction != Action.SPECIAL2 && currentAction != Action.DEFEND) { + + if (currentAction != Action.JUMP && currentAction != Action.FALL) { + changeAction(Action.WALK); } } } + + // 忍者可以在空中攻击 + @Override + protected boolean canAttack() { + return super.canAttack() || currentAction == Action.JUMP || currentAction == Action.FALL; + } } + \ No newline at end of file diff --git a/target/classes/uno/mloluyu/characters/Fighter$Action.class b/target/classes/uno/mloluyu/characters/Fighter$Action.class index d6471bf267b08f8acf23160c7aba2db5c668732d..7f5b8537838f467ec4fd8ed04ebfe9e009b3ab9d 100644 GIT binary patch delta 881 zcmZ|NOHWfl6bJDC^p^W*r)8*$QXZm6wFRsoAj-4gyW;EC#}!{Jj0sUU8WY`g1#wI6 zH*ima!=l6oy7pW6K_s4YN_1tL^xWTc&Y8Jq=0oOd#{As#A~H;RaM$X_yg+yiAmg*qW5rLVuS~rN(B^_@Q5zZV;Nui16Im`LjV8( delta 826 zcmZwF&uu=%c~k;S%fC{|IquoY_-&)}ScvkK;Z`)RxO zp#A7x&42#*$=!zxs%iM_NhX{_RMShC*7ZzvSIrWpRT##A~Sj^F8+JQt)!#OcL` zFidNV0BV-Zzh7UVg6wu{13T7H5ESEraly`nU{bK#7EB5DID(R(oD@_9v!)kUC3S-A zKGTb=%fkbv7upcb8CMeLMTd5yt%>5n<8~>4=skiX-Xc=`{~^So8;+a;30=qK%*; z>dq@#t+-IqKsRa=LQxb^L2xDR`~zHxTUVlL0sJos_Q(QLdVyW+*cvF{Pwll3Vz7Cc2o^zRo zbPH@EhV-g;-h?(N7`W{WDz8IVmM<*Z)P&E}whMxs36>xD-fM*)u<-*5W(B>BOcfV< z((x)Pi?~w6aay_im|ntCqu8~;ZXm~4!*DV7HuNC561DpHzrMMMi7H-BmEd1Zo$8A} zGMUF?9K{oyz&y^Pg!5Ry44z^?=l#pK!vP$ma^no%Vh)0bR4#JadBiMF#|iBx^5s;E zW!Q_npV0fDE{8_iCCtUV#=a7?DgOU!O}QINjGA(&PoZ^USKmT0k8`DBt5sYo+!i?I zh8F>>mnb$M29u1VA4B9YlGsJ=Mh00jheJ3*PU9p_k*9G1m&h4h$4&AU?%*Cd%e{-_ zJf5LUR`3dMB&z1xS__kC-J{FK-&hMFYey96{~f8ng?hFs>l1YeO=5fvn{>)1vYFWy sh-|H&J<>-n0u5KuE&Yi=LABLKY=h`M4iCMde zHuE6TWJWz(&-9h#1-w@CT+)OMYt;#K7qI)>GgvBCm&*7r1u_rjSjOFTOM?q;I zr>awhREMiNE!Jw^zn)oX$c*Ok9Ov-@moSfUEZ`anxPg~Au4F@H2IO%sQ z9204YPr9{u!1qG6#CNGR6>+S@=2sfTLlm1CLnGoyh)MJyBlcks2gHL~%Mo!5CviqR zi^~`nui`o;#9O$BDRCN)@K~JDO6FWO^V&m^G4ruy)8r7Mhiq>7g$(+^XdS*v4(*dUYv~?d5YPyX3XP!X0$6I~!$MQ#bY?$X;f+M?dR_`*pEb IK?_9cH}pSuFaQ7m diff --git a/target/classes/uno/mloluyu/desktop/GameCore.class b/target/classes/uno/mloluyu/desktop/GameCore.class index 67bd9622ca3609c8e0ceaffa8169729e73a4721c..2d615a1eb9a838a714f6d9969cc275e4d758c82a 100644 GIT binary patch delta 893 zcmZuu+fEZv6kTVaw_$)ZjDOOP_ zGfdgPSlC~fRg+u%ja4yu+UeJRY}h+&x9Y(;hT+%Bp^_{rdLg-Hnuh5`h+%zOH+k78 z9&%OA8wVw=s92hz%O%s;EAoRyS@dn~bGp*YmRZSLhAF3uTAs(^vR0NWy2@W^I#)#z zV~9u?#07?6EZddZv`o#V7gF(@-DJlBhU*drAo(C;PQpBH*i~WDeG|7mxMhD7qJ4`< z**}Fb-!krcaEIY?%|B8*8BR!8L7Kr`DXEIZ8Twe1rBt-F;VLIj{cjcdPvdiF6wQ|WQb7%aigsdIu zdsj`8BBT6Wi6i(w5fBid)7@%HI7?V+4`2jAsu)HwMCUN!dGxjJ#IG28890B0@HguA zG6Z`V#12EW!%%$-SBqk)j`6@%=aZV4aDmD*D`;X$K;koI>X>a}fuVsVDpwo0?{wSn zVb^wuj00gZ7eNT)h|{yo;387E)MI3+V>!Fve(NL*m8|H4??d&f1ck&c@cp zLZT2g@d11Qt_UxRQ`R4!UJT#ZQ#^=x52Y`8O6^%Px&7B=H^cNpP`mTLl zxVo^5-#eO)cA0GPi$m2k4YZ-P2@D+^UT_g(`-aSgIYRIWP5JOdkl+}>sQ6Nbv~f)8 zm=LNBpgIHq6i~S>p7+pb%8}`>W26whp(CHBUAkijALpAtAD1Fq$3w+4y;vO4phNN yt@tM<-(U@?YMmiXkwWo0Z74=Ht5-f_4IXMxWp$?;BCZ7noUY-2yD~II!R9aj97d`D diff --git a/target/classes/uno/mloluyu/desktop/character/Alice.class b/target/classes/uno/mloluyu/desktop/character/Alice.class index 353d4894479d385af3218f975aa4f1891d259c6b..5fa4ba2acfbde028439807467fe4e4e4ded07af3 100644 GIT binary patch literal 1902 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 UFetXLU7okFM9dc#ibW{-4{tnxO#lD@