Эх сурвалжийг харах

blinking on heal or damage, image slots (for color overlays), removed entity <-> entity collision, hurt ai tests

Kajetan Johannes Hammerle 7 жил өмнө
parent
commit
c992e0f802

+ 6 - 1
src/me/hammerle/supersnuvi/entity/Entity.java

@@ -159,6 +159,7 @@ public final class Entity
     public void tick() 
     {
         controller.tick();
+        health.tick();
         movePenalty.reset();
         
         if(isAffectedByGravity())
@@ -217,6 +218,11 @@ public final class Entity
         return onGround;
     }   
     
+    public void setNoGround()
+    {
+        onGround = false;
+    }   
+    
     //--------------------------------------------------------------------------
     // collision stuff
     //--------------------------------------------------------------------------
@@ -239,7 +245,6 @@ public final class Entity
         double endX = startX + dirX;
         double endY = startY + dirY;
         
-        
         CollisionBox eBox = getBox();
         double halfWidth = eBox.getWidth() / 2;
         double halfHeight = eBox.getHeight() / 2;

+ 23 - 0
src/me/hammerle/supersnuvi/entity/EntityBuilder.java

@@ -10,6 +10,7 @@ import me.hammerle.supersnuvi.entity.components.HeroItemCollector;
 import me.hammerle.supersnuvi.entity.components.LandMovement;
 import me.hammerle.supersnuvi.entity.components.MovementPenalty;
 import me.hammerle.supersnuvi.entity.components.ai.EntityController;
+import me.hammerle.supersnuvi.entity.components.ai.FollowHeroController;
 import me.hammerle.supersnuvi.entity.components.ai.HumanController;
 import me.hammerle.supersnuvi.entity.components.animator.DefaultAnimator;
 import me.hammerle.supersnuvi.entity.components.animator.EntityAnimator;
@@ -58,6 +59,28 @@ public final class EntityBuilder
         return hero;
     }
     
+    public static Entity buildTest(Level level, double x, double y)
+    {
+        Entity hero = new Entity(level, x, y, 32.0, 64.0);
+        hero.animator = new DefaultAnimator(hero, 0.0, -2.0, "snuvi/snuvi", new String[] 
+                {
+                    "snuvi/snuvi_frame1", "snuvi/snuvi_frame2", "snuvi/snuvi_frame3",
+                    "snuvi/snuvi_frame4", "snuvi/snuvi_frame5", "snuvi/snuvi_frame6",
+                    "snuvi/snuvi_frame7", "snuvi/snuvi_frame8", "snuvi/snuvi_frame9"
+                }, new String[] 
+                {
+                    "snuvi/snuvi_jump"
+                });
+        hero.controller = new FollowHeroController(hero, 1);
+        //hero.controller = new HumanController(hero);
+        hero.health = new DefaultHealth(hero, Death.NULL, 100.0);
+        hero.energy = new DefaultEnergy(hero, 100.0);
+        hero.move = new DefaultMovement(hero, ent -> StateRenderer.CONFIG.getDouble("jump", 10));
+        //hero.itemCollector = new HeroItemCollector(hero);
+        hero.movePenalty = new LandMovement(hero);
+        return hero;
+    }
+    
     public EntityBuilder setController(EntityController controller)
     {
         ent.controller = controller;

+ 28 - 0
src/me/hammerle/supersnuvi/entity/components/DefaultHealth.java

@@ -7,6 +7,8 @@ public class DefaultHealth extends Health
     private final double maxHealth;
     private double health;
     
+    private int hurtTicks;
+    
     public DefaultHealth(Entity ent, Death death, double maxHealth) 
     {
         super(ent, death);
@@ -14,6 +16,31 @@ public class DefaultHealth extends Health
         this.health = maxHealth;
     }
 
+    @Override
+    public void tick() 
+    {
+        if(hurtTicks > 0)
+        {
+            hurtTicks--;
+        }
+        else if(hurtTicks < 0)
+        {
+            hurtTicks++;
+        }
+    }
+
+    @Override
+    public boolean isHurt() 
+    {
+        return hurtTicks > 0;
+    }
+
+    @Override
+    public boolean isHealed() 
+    {
+        return hurtTicks < 0;
+    }
+
     @Override
     public double getMaxHealth() 
     {
@@ -29,6 +56,7 @@ public class DefaultHealth extends Health
     @Override
     public void addHealth(double h) 
     {
+        hurtTicks = h < 0 ? 10 : -5;
         health += h;
         if(health > maxHealth)
         {

+ 1 - 0
src/me/hammerle/supersnuvi/entity/components/DefaultMovement.java

@@ -17,6 +17,7 @@ public class DefaultMovement extends Movement
     {
         if(ent.isOnGround())
         {
+            ent.setNoGround();
             ent.setMotionY(ent.getMotionY() + getJumpPower());
             return true;
         }

+ 5 - 0
src/me/hammerle/supersnuvi/entity/components/Health.java

@@ -51,4 +51,9 @@ public class Health extends Component
     {
         return 0.0;
     }
+    
+    public int getSlot()
+    {
+        return -1;
+    }
 }

+ 22 - 3
src/me/hammerle/supersnuvi/entity/components/ai/FollowHeroController.java

@@ -7,11 +7,13 @@ import me.hammerle.supersnuvi.util.Face;
 public class FollowHeroController extends EntityController
 {
     private final double motion;
+    private boolean jump;
     
     public FollowHeroController(Entity ent, double motion)
     {
         super(ent);
         this.motion = motion;
+        this.jump = false;
     }
 
     @Override
@@ -20,14 +22,19 @@ public class FollowHeroController extends EntityController
         Entity hero = ent.getLevel().getHero();
         if(hero.squaredDistance(ent) <= 102400)
         {
+            if(jump)
+            {
+                jump = false;
+                ent.getMovement().jump();
+            }
             double distance = ent.signedDistanceX(hero);
             if(distance < 0)
             {
-                ent.setMotionX(motion);
+                ent.setMotionX(motion * ent.getMovementPenalty().getFactor());
             }
             else if(distance > 0)
             {
-                ent.setMotionX(-motion);
+                ent.setMotionX(-motion * ent.getMovementPenalty().getFactor());
             }
         }
     }
@@ -35,6 +42,18 @@ public class FollowHeroController extends EntityController
     @Override
     public void onCollideWithEntity(Entity ent, Face face) 
     {
+        if(this.ent.signedDistanceX(ent) == 0)
+        {
+            if(ent.getX() - this.ent.getX() > 0)
+            {
+                ent.setMotionX(6.0);
+            }
+            else
+            {
+                ent.setMotionX(-6.0);
+            }
+            ent.getHealth().addHealth(-0.05);
+        }
     }
 
     @Override
@@ -44,7 +63,7 @@ public class FollowHeroController extends EntityController
                 Math.abs(ent.getPreviousMotionX() - ent.getMotionX()) > 0.001 &&
                 Math.abs(ent.signedDistanceX(ent.getLevel().getHero())) > 0.001)
         {
-            ent.getMovement().jump();
+            jump = true;
         }
     }
 }

+ 0 - 1
src/me/hammerle/supersnuvi/entity/components/ai/HumanController.java

@@ -1,7 +1,6 @@
 package me.hammerle.supersnuvi.entity.components.ai;
 
 import me.hammerle.supersnuvi.entity.Entity;
-import me.hammerle.supersnuvi.gamelogic.Level;
 import me.hammerle.supersnuvi.javafx.KeyHandler;
 import me.hammerle.supersnuvi.util.SoundUtils;
 

+ 46 - 0
src/me/hammerle/supersnuvi/entity/components/animator/DefaultAnimator.java

@@ -1,6 +1,7 @@
 package me.hammerle.supersnuvi.entity.components.animator;
 
 import me.hammerle.supersnuvi.entity.Entity;
+import me.hammerle.supersnuvi.entity.components.Health;
 import me.hammerle.supersnuvi.javafx.Image;
 import me.hammerle.supersnuvi.util.Utils;
 
@@ -16,26 +17,36 @@ public class DefaultAnimator extends EntityAnimator
     private final Image[] moveAir;
     private boolean flipped;
     
+    private int blink;
+    
     public DefaultAnimator(Entity ent, double offsetX, double offsetY, String face, String[] move, String[] moveAir) 
     {
         super(ent, offsetX, offsetY);
         flipped = false;
         counter = 0;
         frame = 0;  
+        blink = 0;
         
         this.face = Utils.getImage(face);
+        this.face.createSlot(255, 0, 0, 255);
+        this.face.createSlot(0, 255, 0, 255);
+        
         this.currentFace = this.face;
         
         this.move = new Image[move.length];
         for(int i = 0; i < move.length; i++)
         {
             this.move[i] = Utils.getImage(move[i]);
+            this.move[i].createSlot(255, 0, 0, 255);
+            this.move[i].createSlot(0, 255, 0, 255);
         }
         
         this.moveAir = new Image[moveAir.length];
         for(int i = 0; i < moveAir.length; i++)
         {
             this.moveAir[i] = Utils.getImage(moveAir[i]);
+            this.moveAir[i].createSlot(255, 0, 0, 255);
+            this.moveAir[i].createSlot(0, 255, 0, 255);
         }
     }
 
@@ -58,6 +69,12 @@ public class DefaultAnimator extends EntityAnimator
         {
             frame = 0;
         }
+        
+        blink++;
+        if(blink > 9)
+        { 
+            blink = 0;
+        }
     }
     
     @Override
@@ -100,4 +117,33 @@ public class DefaultAnimator extends EntityAnimator
         }
         return currentFace;
     }
+    
+    @Override
+    public void bindSlot()
+    {
+        Image i = getImage();
+        if(i != null)
+        {
+            Health h = ent.getHealth();
+            if(h.isHealed())
+            {
+                i.bindSlot(1);
+            }
+            else if(h.isHurt())
+            {
+                if(blink >= 5)
+                {
+                    i.bindSlot(0);
+                }
+                else
+                {
+                    i.bindSlot(-1);
+                }
+            }
+            else
+            {
+                i.bindSlot(-1);
+            }
+        }
+    }
 }

+ 5 - 0
src/me/hammerle/supersnuvi/entity/components/animator/EntityAnimator.java

@@ -1,6 +1,7 @@
 package me.hammerle.supersnuvi.entity.components.animator;
 
 import me.hammerle.supersnuvi.entity.Entity;
+import me.hammerle.supersnuvi.entity.components.Health;
 import me.hammerle.supersnuvi.javafx.Image;
 
 public class EntityAnimator 
@@ -41,4 +42,8 @@ public class EntityAnimator
     {
         return ent.getY() + ent.getHeight() + offsetY;
     }
+    
+    public void bindSlot()
+    {
+    }
 }

+ 7 - 4
src/me/hammerle/supersnuvi/gamelogic/Level.java

@@ -8,9 +8,7 @@ import java.util.TreeSet;
 import java.util.stream.Collectors;
 import me.hammerle.supersnuvi.entity.Entity;
 import me.hammerle.supersnuvi.entity.EntityBuilder;
-import me.hammerle.supersnuvi.entity.components.Energy;
 import me.hammerle.supersnuvi.entity.components.animator.EntityAnimator;
-import me.hammerle.supersnuvi.entity.components.Health;
 import me.hammerle.supersnuvi.tiles.BottledSoulTile;
 import me.hammerle.supersnuvi.tiles.Location;
 import me.hammerle.supersnuvi.tiles.StartTile;
@@ -85,6 +83,10 @@ public final class Level
         }
         
         resetLevel();
+        
+        
+        Entity test = EntityBuilder.buildTest(this, 100, 100);
+        entities.put(entityCounter++, test);
     }
     
     // -------------------------------------------------------------------------
@@ -211,6 +213,7 @@ public final class Level
             entities.values().forEach(en -> 
             {
                 EntityAnimator a = en.getAnimator();
+                a.bindSlot();
                 if(a.drawImageFlipped())
                 {
                     renderer.drawFlippedImage(a.getImage(), a.getRenderX(), a.getRenderY());
@@ -417,10 +420,10 @@ public final class Level
     
     public LinkedList<CollisionBox> getMovementBoxesAt(Entity not, CollisionBox cb)
     {
-        LinkedList<CollisionBox> boxes = new LinkedList<>(entities.values().stream()
+        LinkedList<CollisionBox> boxes = new LinkedList<>(/*entities.values().stream()
                         .filter(ent -> ent != not && ent.getBox().intersects(cb))
                         .map(ent -> ent.getBox())
-                        .collect(Collectors.toList()));
+                        .collect(Collectors.toList())*/);
         int startX = renderer.toBlock(cb.getMinX());
         int endX = renderer.toBlock(cb.getMaxX());
         int startY = renderer.toBlock(cb.getMinY());

+ 61 - 0
src/me/hammerle/supersnuvi/javafx/Image.java

@@ -1,7 +1,68 @@
 package me.hammerle.supersnuvi.javafx;
 
+import javafx.scene.image.PixelReader;
+import javafx.scene.image.PixelWriter;
+
 public abstract class Image 
 {
+    private javafx.scene.image.Image[] colored;
+    private int slot = -1;
+    
+    public Image()
+    {
+        colored = new javafx.scene.image.Image[0];
+    }
+    
+    public void bindSlot(int slot)
+    {
+        this.slot = slot;
+    }
+    
+    public void createSlot(int r, int g, int b, int alpha)
+    {
+        javafx.scene.image.Image[] newColored = new javafx.scene.image.Image[colored.length + 1];
+        System.arraycopy(colored, 0, newColored, 0, colored.length);
+        javafx.scene.image.Image image = getImage();
+        PixelReader reader = image.getPixelReader();
+        int w = (int) image.getWidth();
+        int h = (int) image.getHeight();
+        javafx.scene.image.WritableImage wi = new javafx.scene.image.WritableImage(w, h);
+        PixelWriter writer = wi.getPixelWriter();
+        newColored[colored.length] = wi;
+        colored = newColored;
+        
+        int argb = (alpha << 24) | (r << 16) | (g << 8) | b;
+        for(int x = 0; x < w; x++)
+        {
+            for(int y = 0; y < h; y++)
+            {
+                writer.setArgb(x, y, mixColor(reader.getArgb(x, y), r, g, b, alpha));
+            }
+        }
+    }
+    
+    private int mixColor(int argb, int r, int g, int b, int alpha)
+    {
+        if(argb == 0)
+        {
+            return 0;
+        }
+        int br = (((argb >> 16) & 0xFF) + r) >> 1;
+        int bg = (((argb >> 8) & 0xFF) + g) >> 1;
+        int bb = ((argb & 0xFF) + b) >> 1;
+        int ba = (((argb >> 24) & 0xFF) + alpha) >> 1;
+        return (ba << 24) | (br << 16) | (bg << 8) | bb;
+    }
+    
+    protected final javafx.scene.image.Image getImageSlot()
+    {
+        if(slot < 0 || slot >= colored.length)
+        {
+            return getImage();
+        }
+        return colored[slot];
+    }
+    
     protected abstract javafx.scene.image.Image getImage();
     
     public abstract double getWidth();

+ 7 - 5
src/me/hammerle/supersnuvi/javafx/JavaRenderer.java

@@ -6,6 +6,8 @@ import javafx.scene.Group;
 import javafx.scene.Scene;
 import javafx.scene.canvas.Canvas;
 import javafx.scene.canvas.GraphicsContext;
+import javafx.scene.effect.BlurType;
+import javafx.scene.effect.Shadow;
 import javafx.scene.input.KeyEvent;
 import javafx.scene.paint.Color;
 import javafx.stage.Stage;
@@ -136,23 +138,23 @@ public class JavaRenderer extends Application implements IJavaRenderer
     // -------------------------------------------------------------------------
     // image rendering
     // -------------------------------------------------------------------------
-    
+
     @Override
     public void drawImage(Image image, double x, double y)
     {
-        context.drawImage(image.getImage(), x, y);
+        context.drawImage(image.getImageSlot(), x, y);
     }
     
     @Override
     public void drawImage(Image image, double x, double y, double w, double h)
     {
-        context.drawImage(image.getImage(), x, y, w, h);
+        context.drawImage(image.getImageSlot(), x, y, w, h);
     }
     
     @Override
-    public void drawImage(Image img, double sx, double sy, double sw, double sh, double dx, double dy, double dw, double dh)
+    public void drawImage(Image image, double sx, double sy, double sw, double sh, double dx, double dy, double dw, double dh)
     {
-        context.drawImage(img.getImage(), sx, sy, sw, sh, dx, dy, dw, dh);
+        context.drawImage(image.getImageSlot(), sx, sy, sw, sh, dx, dy, dw, dh);
     }
     
     // -------------------------------------------------------------------------

+ 1 - 1
src/me/hammerle/supersnuvi/rendering/IRenderer.java

@@ -12,7 +12,7 @@ public interface IRenderer
     public void drawFixedImage(Image image, double x, double y);
     public void drawFixedImage(Image image, double x, double y, double w, double h);
     public void drawFlippedImage(Image image, double x, double y);
-    public void drawBlockImage(Image image, int x, int y, double offsetX, double offsetY);   
+    public void drawBlockImage(Image image, int x, int y, double offsetX, double offsetY);  
     
     // -------------------------------------------------------------------------
     // primitive rendering