[Hướng Dẫn] Some GM Tuturials & Examples

[where?][where?] Posts: 149Registered
edited August 2019 in Game Maker: Studio
Sợ bị nói lên forum chỉ chém gió chứ chả đóng góp được gì nên lập thread tổng hợp lại 1 vài post của mình: =]] (Anh Khoa +rep em không em ghen =]])
RTS Unit Control

- vậy mình muốn dùng chuột để chọn 1 đơn vị quân nào đó (như các game RTS) thì nó có hướng dẫn ở đó không nhỉ
Mình đang bận nên làm đại khái:
- Dùng chuột trái chọn nhiều unit 1 lúc theo zone hình chữ nhật.
- Dùng chuột trái chọn 1 unit duy nhất.
- Đặt lệnh cho các unit (ở đây là di chuyển, dùng chuột phải để chọn đích đến).

Do cái script editor của GM không hiển thị tiếng Việt nên mình xin giải thích code ở đây.

Tạo 1 object control, ở dưới dùng trong event Draw:
var unit;
//Xem hiện tại có bao nhiêu unit trong room.
unitCount = instance_number(objBaseUnit);

//Bỏ tất cả ID của các unit vào 1 mảng.
for (i = 0; i < unitCount; i += 1) {
    unit[i] = instance_find(objBaseUnit, i);
}

/* Kiểm tra nếu nhấn chuột trái thì đặt tọa độ vùng chọn theo tọa độ
chuột. Tắt cờ isSelected của tất cả unit và bật cờ isSelected của unit bị click vào. */
if (mouse_check_button_pressed(mb_left)) {
    selectZoneX = mouse_x;
    selectZoneY = mouse_y;
    objBaseUnit.isSelected = false;
    
    for (i = 0; i < unitCount; i += 1) {
        if(collision_point(mouse_x, mouse_y, unit[i], false, true)) {
            unit[i].isSelected = true;
        }else {
            if (unit[i].isSelected) {
                unit[i].desX = mouse_x;
                unit[i].desY = mouse_y;
            }
        }
    }  
}

//Đặt đích đến cho các unit có cờ isSelected bật khi click chuột phải.
if (mouse_check_button_pressed(mb_right)) {
    for (i = 0; i < unitCount; i += 1) {
        if (unit[i].isSelected) {
            unit[i].desX = mouse_x;
            unit[i].desY = mouse_y;
       }
    }  
}

/* Bật cờ của tất cả các unit nằm trong hình chữ nhật
(selectZoneX, selectZoneY, mouse_x, mouseY) */
if (mouse_check_button_released(mb_left)) {
    for (i = 0; i < unitCount; i += 1) {
        if ((unit[i].x > selectZoneX) && (unit[i].y > selectZoneY) 
        && (unit[i].x < mouse_x) && (unit[i].y < mouse_y)) {
            unit[i].isSelected = true;
        }
    }
}

/* Vẽ vùng chọn lên màn hình. Trong example này do không có thời giàn nên mình chỉ active vùng chọn khi (mouse_x > selectZoneX) và
(mouse_y > selectZoneY). Bạn có thể sửa lại bằng cách check nếu tọa 
độ của mouse bé hơn tọa độ gốc của vùng chọn thì tọa độ gốc của vùng
chọn sẽ là tọa độ mouse và tọa độ ta lấy ban đầu khi click chuột sẽ
thành tọa độ góc phải bên dưới. */
if (mouse_check_button(mb_left)) {
    if ((mouse_x > selectZoneX) && (mouse_y > selectZoneY)) {
        draw_set_color(c_green);
        draw_rectangle(selectZoneX, selectZoneY, mouse_x, mouse_y, true);
    }
}

Trong event Draw của objBaseUnit:
//Nếu unit đang được chọn thì vẽ 1 hình tròn màu xanh bao quanh nó.
if (isSelected) {
    r = sprite_width;
    if (sprite_height > sprite_width) r = sprite_height;
    draw_set_color(c_green);
    draw_circle(x, y, r, true);
}

//Di chuyển tới đích được đặt, né các vật cản solid.
action_potential_step(desX, desY, moveSpeed, 0);

/*Do object này sử dụng event draw nên sprite của nó sẽ không được
tự động render lên màn hình, bên dưới ta vẽ lại sprite.*/
draw_sprite_ext(sprite_index, image_index, x, y, image_xscale, image_yscale, image_angle, image_blend, image_alpha);

Bạn muốn làm 1 game RTS hoàn chỉnh thì còn phải làm nhiều nhiều lắm, example mình chỉ làm phần cơ bản vậy thôi.
Download
https://taotrochoi.com/vanilla/home/leaving?https://dl.dropboxusercontent.com/u/58156219/Linh Tinh/rts_unit_control.gmk
In Sign Aiming and Shooting

- mình muốn đạn bay theo hướng đứng của player và enemy có thể bắn khi thấy player thì làm thế nào?

Example: https://dl.dropboxusercontent.com/u/58156219/Linh Tinh/aiming.gmk

Nhìn vào event Step của objEnemy:
distanceToShoot = 250;

if (canShoot)
if (distance_to_object(objPlayer) < distanceToShoot) {
    bl = instance_create(x, y, objEneBullet);
    bl.direction = point_direction(x, y, objPlayer.x, objPlayer.y);
    bl.speed = 5;
    canShoot = false;
    alarm[0] = 30;
}

- Method distance_to_object(obj): Khi bạn gọi method này trong Object thì nó sẽ trả về khoảng cách giữa Object với obj. Trong demo mình đặt là khi objPlayer tới gần objEnemy trong phạm vi 250 thì objEnemy sẽ bắn.

- Function point_direction(x1, y1, x2, y2): Function này trả về direction từ (x1, y1) đến (x2, y2). Bạn dùng cái này để tính direction cho objEneBullet.

Ghi chú: Nếu bạn cho camera (view) chạy theo player thì bạn có thể check nếu objEnemy đi vào view thì cho nó bắn, sử dụng view_xport, view_yport, view_wport, view_hport, view border này nọ tùy setting của bạn.



[size=medium]Potent Movement[/size]

- Hỏi cách làm cho monster đuổi theo nhân vật

Trong event Step của 1 object bạn dùng hàm action_potential_step để cho object đó liên tục di chuyển theo 1 tọa độ nào đó. Hàm này cho phép object tự tìm đường đi qua các chướng ngại để đến đích.
action_potential_step(desX, desY, stepSize, avoidAll)
desX: Hoành độ của đích.
desY: Tung độ của đích.
stepSize: Có thể hiểu là tốc độ di chuyển, nhưng chính xác là giá trị để update x và y của object sau mỗi lần hàm này được gọi.
avoidAll: true nếu né tất cả các object, false nếu chỉ né solid object.

Mỗi khi hàm này được gọi nó sẽ thay đổi vị trí của object gọi nó theo tham số stepSize hướng theo tọa độ đích được nhập vào và né các đối tượng chắn đường.

File example, các bạn mở ra xem là tiện nhất:
https://dl.dropboxusercontent.com/u/58156219/Linh Tinh/following.gmk

Mình đang bận và không muốn làm rối example nên coi như player đi xuyên tường nhé.

Lưu ý dù là có set né hay không né solid object khi dùng hàm action_potential_step thì các vật thể về bản chất vật lý là cứng và không chuyển động như tường thì bạn nên chuyển nó thành solid (tick vào ô solid).

Và 1 điều nữa là bạn không cần script cũng được, tại bên action phần Move / Steps có cái action thứ 2 bên trái sang. Cứ kéo thả nó vô rồi xài thôi, các tham số như cái hàm action_potential_step cả trừ 1 cái option là relative. Tick nó vào thì desX và desY sẽ trở thành vị trí tương đối với x, y của object. Đại khái khi bạn tick vào nó thì nó sẽ tương đương thế này:
action_potential_step(x + desX, y + desY, stepSize, avoidAll)

Trong trường hợp bạn muốn làm đơn giản không có né tránh vật cản:
//Bỏ phần else đi nếu không muốn nó đuổi dí sát, đè lên player.
 var runSpeed = 5;
 if (x < objPlayer.x - runSpeed) x += runSpeed; else x = objPlayer.x;
 if (x > objPlayer.x + runSpeed) x -= runSpeed; else x = objPlayer.x;
 if (y < objPlayer.y - runSpeed) y += runSpeed; else y = objPlayer.y;
 if (y > objPlayer.y + runSpeed) y -= runSpeed; else y = objPlayer.y;

Xem thêm về motion planning bằng GML: http://www.gmlscripts.com/gml/motion_planning

Comments

Sign In or Register to comment.