Dungeon rpg announcement

I made 2 simple games and I hope that I have enough experience to make rpg
the game will:
player
monsters
loot
cloth
chests

so far a simple demo
of course he must be in clothes
spinning with a sword
and hit with a shield

6 Likes

users have asked me to share combat code and progress bar

mosnter

/*
 * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
 * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
 */
package components;

import com.jme3.anim.AnimComposer;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.simsilica.es.EntityComponent;
import com.simsilica.es.EntityId;

/**
 *
 * @author ivan
 */
public class Monster  implements EntityComponent{
    //node to attah
    public Node npcNode;
    //mosnte spatial
    public Spatial spatial;
    //monste control
    public CharacterControl control;
    //monster anim composer
    public AnimComposer anim;
    
    //monster stats
    public double hp= 100;
    public double damage = 15;
    public String name;
    
    public double currentHP = 100;
    public EntityId id;
}

add monster

public void loadNPC(float x, float y,float z, String name){
        //create zay es entity
        EntityId monsterId = data.createEntity();
        
        //create new monster
        Monster monster = new Monster();
        monster.name = name;
        monster.npcNode = npcNode;
        monster.id = monsterId;
        
        //load mosnter by name
        Spatial model = assetManager.loadModel("Models/monsters/"+name+".glb");
        //setup zay es id to staptial name for detec from collision
        String id = Long.toString(monsterId.getId()); 
        model.setName( id);
        
        
        
        //setum monster CharacterControl control
        SphereCollisionShape sphereShape = new SphereCollisionShape(2.0f);
        CharacterControl myThing_phys = new CharacterControl( sphereShape , 1.2f );
        model.addControl(myThing_phys);
        
        monster.control = myThing_phys;
        
        physics.getPhysicsSpace().add(myThing_phys);

        physics.getPhysicsSpace().add(model);
        
        //setum monster control with monster logic
        model.addControl(new EnemyControl(data,playerId,monster));
        myThing_phys.setPhysicsLocation(new Vector3f(x,y,z));
        
        //setup anima composer
        Node monsterNode = (Node)model;
        Node armature = (Node)monsterNode.getChild(0);
            
        
        
        AnimComposer animComposer = armature.getControl(AnimComposer.class);        
        monster.anim = animComposer;
        monster.anim .setCurrentAction("stand");
        
        model.scale(1.2f);
        npcNode.attachChild(model);
        
        monster.spatial = model;
        
        //add monster component to zay es
        data.setComponent(monsterId, monster);

        
    
    }

monster logic in control

/*
 * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
 * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
 */
package controls;

import com.jme3.anim.AnimLayer;
import com.jme3.anim.tween.action.Action;
import com.jme3.animation.AnimChannel;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;
import com.simsilica.es.Entity;
import com.simsilica.es.EntityData;
import com.simsilica.es.EntityId;
import components.Monster;
import components.PlayerStat;
import components.PlayerVisual;
import java.time.Instant;
import java.util.Set;

/**
 *
 * @author ivan
 */
public class EnemyControl extends AbstractControl{
    EntityData data;
    EntityId playerId;
    Monster monster;
    PlayerVisual playerVisual;
    PlayerStat playerStat;
    AnimChannel attackChanel;
    
    public EnemyControl(EntityData data, EntityId playerId,Monster monster) {
        this.data = data;
        this.playerId = playerId;
        this.monster = monster;
        
        Entity entity = data.getEntity(playerId, PlayerVisual.class);

        playerVisual = entity.get(PlayerVisual.class);
       
        entity = data.getEntity(playerId, PlayerStat.class);
        
        playerStat = entity.get(PlayerStat.class);
        

    }

    public void setSpatial(Spatial spatial) {
        super.setSpatial(spatial);
    }
    
    private float interp = 0.0f;
    private float mySpeed = 0.05f;
    private Vector3f  walkDirection = new Vector3f(0,0,0);
    private float agrDistance = 15f;
    private boolean agr = false;
    private boolean isRun = false;
    private boolean isAttack = false;
    private boolean isAlive = true;
    
    @Override
    protected void controlUpdate(float f) {
        //
        if(monster.currentHP <= 0){
            isAlive = false;
        }
        walkDirection.set(0, 0, 0);

        Vector3f monsterPosition = monster.control.getPhysicsLocation();
        Vector3f playerPosition = playerVisual.characterControl.getPhysicsLocation();     

        float distance = playerPosition.distance(monsterPosition);
        interp += (mySpeed/distance) * f;
        //if moster alive
        
        if(isAlive){
            //monster agr
            if(distance < agrDistance && agr == false){
                agr = true;
            }
            
            //move monster
            if ( distance > 3 && agr) {
                //direction to player
                Vector3f direction = playerPosition.subtract(monsterPosition).normalize();
                //set monster view direction to player
                monster.control.setViewDirection(direction);

                //add direction 
                walkDirection.addLocal(direction);
                //set walk direction
                monster.control.setWalkDirection(walkDirection.mult(0.05f));
                if(isRun == false){

                    monster.anim.setCurrentAction("run");
                    isRun = true;
                }
                isAttack = false;
            }else if(distance <= 3){
                //monster stand and attack
                
                //set walk direction 0
                walkDirection.set(0, 0, 0);
                monster.control.setWalkDirection(walkDirection);
               
                isRun = false;
                //attak animation
                if(isAttack == false){
                   monster.anim.setCurrentAction("attack");
                   
                    isAttack= true;
                }
                //remove mosnter damage from player
                if(nextAttack < Instant.now().getEpochSecond()){
                    playerStat.currentHp = playerStat.currentHp + playerStat.def - monster.damage;
                    nextAttack = Instant.now().getEpochSecond()+1;
                    
                }

            }
        }else{
            //monster die and remove
            if(isRemove == false){
                
                if(removeTime == 0){
                    removeTime = Instant.now().getEpochSecond() +7;

                }
                if(removeTime == Instant.now().getEpochSecond()){
                    monster.npcNode.detachChild(spatial);
                    data.removeEntity(monster.id);

                    isRemove = true;
                }
            }
        }
        

        
    }
    long removeTime = 0;
    boolean isRemove = false;
    
    public long nextAttack = 0;
    
    @Override
    protected void controlRender(RenderManager rm, ViewPort vp) {
    
    }
    
}

wiki:
zay es

hello collision for move monster logic in control

custom control for monster logic

1 Like

monster hp progress bar
init

 GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
        int w = gd.getDisplayMode().getWidth();
        int h = gd.getDisplayMode().getHeight();

        targetWindows = new Container();
        
        targetWindows.setLocalTranslation(w/2 -160 , h-270, 0);
        targetLabel = new Label("Hello, World.");

        targetWindows.addChild(targetLabel);
        
        targetProgress = new ProgressBar("glass");
        targetProgress.setProgressValue(20);
        targetProgress.setLocalScale(3, 0.75f, 0);
        targetWindows.addChild(targetProgress);

shoose monster to target

 if (name.equals("Target") && !keyPressed) {
        
        //mouse click direction
        Vector3f origin = cam.getWorldCoordinates(inputManager.getCursorPosition(), 0.0f);
        
        Vector3f direction = cam.getWorldCoordinates(inputManager.getCursorPosition(), 0.3f);

        direction.subtractLocal(origin).normalizeLocal();

        
        CollisionResults results = new CollisionResults();
        //create ray
        Ray ray = new Ray( cam.getLocation() , direction );
        

        //collide mouse click wit npc node
        npcNode.collideWith( ray, results );
        
        if( results.size() > 0 ){
            //get clicked spatil
            Spatial npcSpatial = (Spatial)results.getCollision(0).getGeometry().getParent().getParent();
            
            //get target monster
            EntityId targetId = new EntityId(Long.parseLong(npcSpatial.getName()));
            
            Entity entity = data.getEntity(targetId, Monster.class);

            targetMonster = entity.get(Monster.class);
            
            //setup progress label
            targetLabel.setText(targetMonster.name);

            //calsulate progress bar % form monste hp
            double hp = targetMonster.hp;

            double onePercent = hp/100;
            double percent = targetMonster.currentHP/onePercent;
            //setup % value
            targetProgress.setProgressValue(percent);
            
                
            //attach videows
            if(isNoTrager){
                guiNode.attachChild(targetWindows);
            }
            

        }

wiki:
piking

lemur wiki

1 Like

player attack monster
setup keys

      inputManager.addMapping("Shild",new KeyTrigger(KeyInput.KEY_F4)); 

      inputManager.addMapping("Attack",new KeyTrigger(KeyInput.KEY_F1));       inputManager.addListener(actionListener, "Run","Target","Attack","Fury","Kick","Shild");

player attack monster

final private ActionListener actionListener = new ActionListener() {
    @Override
    public void onAction(String name, boolean keyPressed, float tpf) {
         if (name.equals("Shild") && !keyPressed) {
          // if you have target
          if(targetMonster != null){
            //get location and distance
            Vector3f playerLocation = playerVisual.characterControl.getPhysicsLocation();
            Vector3f monsterLocation = targetMonster.control.getPhysicsLocation();
            float distance = playerLocation.distance(monsterLocation);
            //if distance and nex attack time
            if(distance < 4f && nextAttack < Instant.now().getEpochSecond()){
                
                isAttack = true;
                //run animation hit shil
                playerVisual.anim.setCurrentAction("shild");
                //time to change animation to stand
                toStandTime = System.currentTimeMillis() +500;
                
                //get direction to wiev to monster
                Vector3f direction = monsterLocation.subtract(playerLocation).normalize();
                
                Vector3f  correction = new Vector3f(direction.x,direction.y-0.35f,direction.z);
                //set view direction
                playerVisual.characterControl.setViewDirection(correction);
                
                //remove player attak from monster hp
                targetMonster.currentHP = targetMonster.currentHP - playerStat.damage;
                
                //calculate % hp to pgoress bar
                double hp = targetMonster.hp;

                double onePercent = hp/100;
                double percent = targetMonster.currentHP/onePercent;
                //setup % to pgoress bat
                targetProgress.setProgressValue(percent);
                //monster die
                if(targetMonster.currentHP <=0){
                    targetMonster.anim.setCurrentAction("die");
                    guiNode.detachChild(targetWindows);
                    isNoTrager = true;
                }
                nextAttack = Instant.now().getEpochSecond() + 1;
                
            }
          }
      }

wiki

1 Like

I don’t know if you want any feedback from your code or not. But since it is here, like you said, as a requested example… There are these two things…

 GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
        int w = gd.getDisplayMode().getWidth();
        int h = gd.getDisplayMode().getHeight();

If I understand correctly, this is used to position some UI elements. This wont work unless you are really running on default screen resolution and only that. And that Java is in agreement with LWJGL / GLFW. You should instead query screen resolution from jME. Or rather canvas size, not screen resolution.

public class Monster  implements EntityComponent

This one… Well, this is a complicated architectural thing and as such it is not so black and white. But I have a sense that you did not entirely grasp the ECS principle and separation of game logic and visuals. Again, whether this is intended or not I do not know. This design however might hurt you in the future and serves as a poor example to learn from.

Monster is your entity, represented by EntityId. It is not a component typically. In ECS you add qualities via composition, components, to your entity. How fine grained your components are, depend on your scope and overall design. They are meant to be shared by many types of entities you might have. And basically describe a common quality of entity of which logic is handled by a System.

So you could break your Monster component to several components, like Position (you now represent this via Node I suppose), Health, Damage, Creature (for housing name and indicating a living thing) and Visual (for housing model name etc.). Then add these components to your Entity, that Entity then becomes the Monster you always wanted it to be…

Your i.e. AppState can then link the entity to Spatial, Node, whatever you use jME for actually showing it to the user. This is separating visuals. Your ECS system should be ideally complete void of all jME stuff. That comes in just on the visual layer.

pspeed has compiled those examples with love clearly. Breath them in, slowly, to grasp ECS and become a legend in the game development industry!

1 Like

always happy for advice

If I understand correctly, this is used to position some UI elements. This wont work unless you are really running on default screen resolution and only that. And that Java is in agreement with LWJGL / GLFW. You should instead query screen resolution from jME. Or rather canvas size, not screen resolution.

how to? :slight_smile:

So you could break your Monster component to several components, like Position (you now represent this via Node I suppose), Health, Damage, Creature (for housing name and indicating a living thing) and Visual (for housing model name etc.). Then add these components to your Entity, that Entity then becomes the Monster you always wanted it to be…

Monster{
   MonsterVisual monsterVisual;
   MonsterStat monsterStat;
}

?

This is composition yes. But… ECS, especially with the Zay-ES library now. EntitData is where you add and get this information. Don’t store it to some arbitrary class. It is a stale component after awhile. Please look at the examples in the library. Or OpenKeeper:

Notice how a creature entity is just composed of many components. Components get added, removed and updated. Zay-ES will take care of this for you. Please see the examples and read the wiki linked already several times in several of your topics.

2 days progress inventory cloth system

2 Likes

pretty awesome man that looks super functional

Loot system

3 Likes

dungeon rpg game play

4 Likes