Minecraft Client 教程 #12 绘制ClickGUI

首发于Enaium的个人博客



一. 先复制进去FontUtils

FontUtils

package cn.enaium.coreium.utils;

import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.util.StringUtils;

public class FontUtils {
    private static FontRenderer fontRenderer;

    public static void setupFontUtils() {
        fontRenderer = Minecraft.getMinecraft().fontRendererObj;
    }

    public static int getStringWidth(String text) {
        return fontRenderer.getStringWidth(StringUtils.stripControlCodes(text));
    }

    public static int getFontHeight() {
        return fontRenderer.FONT_HEIGHT;
    }

    public static void drawString(String text, int x, int y, int color) {
        fontRenderer.drawString(text, x, y, color);
    }

    public static void drawStringWithShadow(String text, double x, double y, int color) {
        fontRenderer.drawStringWithShadow(text, (float)x, (float)y, color);
    }

    public static void drawCenteredString(String text, int x, int y, int color) {
        FontUtils.drawString(text, x - fontRenderer.getStringWidth(text) / 2, y, color);
    }

    public static void drawCenteredStringWithShadow(String text, double x, double y, int color) {
        FontUtils.drawStringWithShadow(text, x - (double)(fontRenderer.getStringWidth(text) / 2), y, color);
    }

    public static void drawTotalCenteredString(String text, int x, int y, int color) {
        FontUtils.drawString(text, x - fontRenderer.getStringWidth(text) / 2, y - fontRenderer.FONT_HEIGHT / 2, color);
    }

    public static void drawTotalCenteredStringWithShadow(String text, double x, double y, int color) {
        FontUtils.drawStringWithShadow(text, x - (double)(fontRenderer.getStringWidth(text) / 2), y - (double)((float)fontRenderer.FONT_HEIGHT / 2.0f), color);
    }
}

二. 开始绘制

ClickGUI

package cn.enaium.coreium.gui.clickgui;

import cn.enaium.coreium.module.Category;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.GuiScreen;

import java.io.IOException;
import java.util.ArrayList;

public class ClickGUI extends GuiScreen {

    public ArrayList<CategoryPanel> categoryPanels;

    public ClickGUI() {
        //添加Category
        categoryPanels = new ArrayList<>();
        int categoryPanelsY = 5;
        for (Category c : Category.values()) {
            categoryPanels.add(new CategoryPanel(c, 5, categoryPanelsY, 100, 20));
            categoryPanelsY += 30;
        }
    }

    @Override
    public void drawScreen(int mouseX, int mouseY, float partialTicks) {
        for (CategoryPanel c : categoryPanels) {
            c.drawScreen(mouseX, mouseY);//绘制所有Category
        }
        super.drawScreen(mouseX, mouseY, partialTicks);
    }

    @Override
    public void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
        for (CategoryPanel c : categoryPanels) {
            c.mouseClicked(mouseX, mouseY,mouseButton);//调用所有CategoryPanel的mouseClicked方法
        }
        super.mouseClicked(mouseX, mouseY, mouseButton);
    }

    @Override
    public void mouseReleased(int mouseX, int mouseY, int state) {
        for (CategoryPanel c : categoryPanels) {
            c.mouseReleased(mouseX, mouseY,state);//调用所有CategoryPanel的mouseReleased方法
        }
        super.mouseReleased(mouseX, mouseY, state);
    }

    public static boolean isHovered(int mouseX, int mouseY, int x, int y, int width, int height) {
        return mouseX >= x && mouseX - width <= x && mouseY >= y && mouseY - height <= y;//获取鼠标位置是否在指定位置
    }

    public static void drawRect(int x, int y, int width, int height, int color) {
        Gui.drawRect(x, y, x + width, y + height, color);//绘制Rect
    }
}

CategoryPanel

package cn.enaium.coreium.gui.clickgui;

import cn.enaium.coreium.Coreium;
import cn.enaium.coreium.module.Category;
import cn.enaium.coreium.module.Module;
import cn.enaium.coreium.utils.FontUtils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.Gui;

import java.awt.*;
import java.util.ArrayList;

public class CategoryPanel {

    private Category category;
    private boolean hovered;
    //单独Category的位置
    private int x;
    private int y;
    //单独Category的长高
    private int width;
    private int height;

    public boolean dragging;//是否为移动状态
    //临时单独Category的位置(上一个位置)
    private int tempX;
    private int tempY;
    //是否显示ModulePanel
    private boolean displayModulePanel;
    //ModulePanel列表
    private ArrayList<ModulePanel> modulePanels;

    public CategoryPanel(Category category, int x, int y, int width, int height) {
        this.category = category;
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        FontUtils.setupFontUtils();//设置Font
        modulePanels = new ArrayList<>();

        ArrayList<Module> modules = new ArrayList<>();
        modules.addAll(Coreium.instance.moduleManager.getModulesForCategory(this.category));//获取该分类所以Module
        for (Module m : modules) {
            modulePanels.add(new ModulePanel(m));//添加ModulePanel
        }
    }

    public void drawScreen(int mouseX, int mouseY) {
        this.hovered = ClickGUI.isHovered(mouseX, mouseY, this.x, this.y, this.width, this.height);//获取鼠标是否在指定位置
        if (this.dragging) {
            //移动CategoryPanel
            this.x = this.tempX + mouseX;
            this.y = this.tempY + mouseY;
        }
        //改变Category颜色
        int color = new Color(0, 190, 255).getRGB();
        if (this.hovered) color = new Color(0, 88, 120).getRGB();
        ClickGUI.drawRect(x, y, this.width, this.height, color);//绘制Category背景
        FontUtils.drawCenteredString(this.category.name(), x + this.width / 2, y + this.height / 2, Color.WHITE.getRGB());//绘制Category的标题
        int modulePanelsY = this.y + this.height;
        //绘制该Category下的所有Module
        if(this.displayModulePanel) {
            for (ModulePanel module : modulePanels) {
                module.drawScreen(mouseX,mouseY,this.x + 10, modulePanelsY, 80, 20);
                modulePanelsY += 20;
            }
        }
    }

    public void mouseClicked(int mouseX, int mouseY, int mouseButton) {
        //如果鼠标在指定位置
        //如果鼠标左键按下
        if (this.hovered && mouseButton == 0) {
            //移动状态为true
            dragging = true;
            //给临时坐标赋值
            this.tempX = this.x - mouseX;
            this.tempY = this.y - mouseY;
        } else if (this.hovered && mouseButton == 1) {//如果鼠标右键被按下
            this.displayModulePanel = !this.displayModulePanel;//是否显示Module
        }
        for (ModulePanel modulePanel : modulePanels) {//调用所有ModulePanel的mouseClicked方法
            modulePanel.mouseClicked(mouseX,mouseY,mouseButton);
        }
    }

    public void mouseReleased(int mouseX, int mouseY, int state) {
        //如果鼠标左键被释放退出移动Category模式
        if (state == 0) {
            this.dragging = false;
        }
    }

}

ModulePanel

package cn.enaium.coreium.gui.clickgui;

import cn.enaium.coreium.module.Module;
import cn.enaium.coreium.utils.FontUtils;

import java.awt.*;

public class ModulePanel {

    private Module module;
    private boolean hovered;

    public ModulePanel(Module module) {
        this.module = module;
        FontUtils.setupFontUtils();//设置Font
    }

    public void drawScreen(int mouseX, int mouseY, int x, int y, int width, int height) {
        this.hovered = ClickGUI.isHovered(mouseX, mouseY, x, y, width, height);//鼠标是否在指定位置
        int color = new Color(200, 190, 255).getRGB();//颜色
        if (this.module.isToggle()) color = new Color(200, 0, 120).getRGB();//Module打开的颜色
        if (this.hovered) color = new Color(200, 88, 120).getRGB();//鼠标在指定位置的颜色
        ClickGUI.drawRect(x, y, width, height, color);//绘制Module的背景
        FontUtils.drawCenteredString(this.module.getName(), x + width / 2, y + height / 2, Color.WHITE.getRGB());//绘制Module的名字
    }

    public void mouseClicked(int mouseX, int mouseY, int mouseButton) {
        if(this.hovered && mouseButton == 0) {
            this.module.toggle();//当鼠标在指定位置并且鼠标被按下设置Module为关闭或打开
        }
    }
}

三. 打开ClickGUI

Click

package cn.enaium.coreium.module.modules.render;

import cn.enaium.coreium.gui.clickgui.ClickGUI;
import cn.enaium.coreium.module.Category;
import cn.enaium.coreium.module.Module;
import org.lwjgl.input.Keyboard;

public class Click extends Module {
    public Click() {
        super("ClickGUI", Keyboard.KEY_RSHIFT, Category.RENDER);
    }

    @Override
    public void onEnable() {
        super.onEnable();
        mc.displayGuiScreen(new ClickGUI());
        toggle();
    }
}

getModulesForCategory

    public ArrayList<Module> getModulesForCategory(Category c) {
        ArrayList<Module> modules = new ArrayList<>();

        for (Module m : this.modules ) {
            if(m.getCategory().equals(c))
                modules.add(m);
        }

        return modules;
    }

原文地址:https://www.cnblogs.com/Enaium/p/12541561.html

时间: 2024-08-30 15:57:05

Minecraft Client 教程 #12 绘制ClickGUI的相关文章

Minecraft Client 教程 #11 绘制主菜单

首发于Enaium的个人博客 一. 搜索GuiMainMenu这个类 二. 删除drawScreen方法内所有 三. 删除无用方法(显示为灰色的方法) 四. 在drawScreen方法绘制 public void drawScreen(int mouseX, int mouseY, float partialTicks) { //获取屏幕长和高 ScaledResolution s = new ScaledResolution(mc); //绑定纹理(材质) mc.getTextureManag

Minecraft Client 教程 #1 配置开发环境

首发于Enaium的个人博客 需要 JAVA8+ 和 IDEA 一. 下载MCP 二. 解压到你想要的路径,文件名你想起什么名字就起什么名字 三. 打开文件夹运行decompile.bat,Linux 或者Mac OS 运行decompile.sh(这一步必有正版启动器,而且默认目录%APPDATA%.minecraft\versions 必须要有MC1.8.8版本,运行前还要运行过1.8.8MC.) 反编译完成 四. 导入IDEA Next Next Next Finish 填写你的导入的目录

Minecraft Fabric Client 教程 #3 添加自定义Command

首发于Enaium的个人博客 package cn.enaium.excel.utils; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.hud.ChatHud; import net.minecraft.text.LiteralText; import net.minecraft.text.Text; /** * @Author Enaium * @Date 2020/1/5 12:54

Minecraft Fabric Client 教程 #2 修改文件和目录名添加run和stop

首发于Enaium的个人博客 修改 包名.json文件.添加run stop 首先先修改包名 将ExampleMod.java改为ExcelInitializer.java 修改json文件modid.mixins.json和fabric.mod.json 将modid.mixins.json改为excel.mixins.json excel.mixins.json内容: { "required": true, "package": "cn.enaium.

Python教程12

Python教程12 1.udp发送数据: import socket def main(): # 创建一个udp套接字 udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 第一个参数是ipv4协议,第二个参数是udp # 使用套接字发送数据,第一个参数是发送数据,第二个参数是一个元祖 # udp_socket.sendto(b"jnjhhjdik111jj5555", ("192.168.1.7&q

Java简明教程 12.多线程(multithreading)

单线程和多线程 关于它们的区别,zhihu上有一个回答,我认为十分不错,如下: 1. 单进程单线程:一个人在一个桌子上吃菜. 2. 单进程多线程:多个人在同一个桌子上一起吃菜. 3. 多进程单线程:多个人每个人在自己的桌子上吃菜. 多线程的问题是多个人同时吃一道菜的时候容易发生争抢.例如两个人同时夹一个菜,一个人刚伸出筷子,结果伸到的时候已经被夹走菜了.此时就必须等一个人夹一口之后,在还给另外一个人夹菜,也就是说资源共享就会发生冲突争抢. 例子: 多线程: 浏览器浏览一个页面,里面有很多图片,多

Unix/Linux环境C编程入门教程(12) openSUSECCPP以及Linux内核驱动开发环境搭建

1. openSUSE是一款优秀的linux. 2.选择默认虚拟机 3.选择稍后安装操作系统 4.选择linux  opensuse 5. 选择默认虚拟机名称 6.设置处理器为双核. 7.内存设置为2G 8. 选择网络地址转换 9.设置IO控制器 10. 选择默认磁盘类型 11.创建一个新的虚拟磁盘 12.设置磁盘大小 13.选择路径保存虚拟磁盘 14. 完成虚拟机创建 15.设置虚拟机 16.选择opensuse镜像 17.开启虚拟机 18.虚拟机启动 19.安装opensuse 20.安装程

【v2.x OGE教程 12】 关卡编辑器帮助文档

[v2.x OGE教程 12] 关卡编辑器帮助文档 一.简介 关卡编辑器用于游戏关卡界面元素的可视化编辑,包括元素的位置.尺寸以及其它自定义属性.通过解析生成的数据文件即可获取关卡信息,并能随时调整,以减少开发工作量,提高开发效率. 二.界面 主界面 图01_主界面 1) 画布 ① 简介 画布用于关卡元素的预览,并提供元素选择和坐标设置等功能:画布的尺寸与其正在显示的关卡的尺寸相同 图02_画布 ② 选择元素 a. 单选:鼠标左键单击即可选中单个元素,选中后的元素周围出现蓝色的方框,未选中的则为

canvas教程(三) 绘制曲线

经过 canvas 教程(二) 绘制直线 我们知道了 canvas 的直线是怎么绘制的 而本次是给大家带来曲线相关的绘制 绘制圆形 在 canvas 中我们可以使用 arc 方法画一个圆 context.beginPath(); context.arc(x, y, r, startRadian, endRadian, antclockwise); context.closePath(); 我们是第一次用到 beginPath 和 closePath 这两个方法,首先这两个方法故名思意就是开始路径