23
Registriert seit: 03.02.2003
Alter: 29
Beiträge: 3.068
|
Genocide_Movement
Was ich hier unter der Hand weggegeben hab, habe ich nun fertig gestellt (d.h., die in dem Topic beschriebenen Bugs behoben) und wollte es hier separat noch einmal vorstellen. Es handelt sich um einen Teil meiner Arbeit für Genocide und bewirkt, dass sich der Held sowie die Events um halbe bzw. Viertelfelder fortbewegen können. Wie eigentlich alles an Genocide ist es auf Performance optimiert.
Am Anfang des Skriptes findet ihr ein paar Einstellungen, inklusive Beschreibung was sie machen.
Viel Spaß.
Code:
# Genocide_Movement 1.1 - 8 pixel precise movement for RPG Maker XP
#
# Author: derula
#
# This script is taken from the German RPGXP project "Genocide" and adjusted
# for standalone usage. Permission is granted by the author to freely use and
# edit it as long as the game "Genocide" and the code's original author remain
# credited in the code. Other means of crediting are voluntary, but appreciated.
module Genocide_Movement
# Hier: Konfiguration
# Um wie viele Viertelfelder soll sich ein Event standardmäßig bewegen?
# (um ein Event um weniger zu bewegen, muss ein Skript benutzt werden)
# Standard: 4, Minimum: 1, Maximum: 4
EVENT_DISTANCE = 4
# Um wie viele Viertelfelder soll sich der Spieler standardmäßig bewegen?
# (um den Spieler um weniger zu bewegen, muss ein Skript benutzt werden)
# Standard: 1, Minimum: 1, Maximum: 4
PLAYER_DISTANCE = 1
# Diagonallaufen aktivieren oder deaktivieren
# Standard: true, Deaktivieren: false
PLAYER_8_DIR = true
# Taste für Strafe: Während diese Taste gedrückt ist, dreht sich der Spieler
# nicht automatisch in die Richtung, in die er geht.
# Standard: Input::SHIFT, Deaktivieren: nil
STRAFE_KEY = Input::SHIFT
# Kosten für Diagonalgehen
# Standard: Math.sqrt(2), Deaktivieren: nil
DIAGONAL_COST = Math.sqrt(2)
class ::Numeric
# Mapfeldkoordinate berechnen aus Fließpunktkoordinate
def to_field
if (i = to_i) == self
i
else
(self-0.125).round
end
end
end
class ::Game_Character
#--------------------------------------------------------------------------
# * Calculate new position
# x : x-coordinate
# y : y-coordinate
# d : direction (0,1,2,3,4,6,7,8,9)
# * 0 = no change
# s : steps (1..4)
#--------------------------------------------------------------------------
def get_new_coordinates(x, y, d, s = EVENT_DISTANCE)
# Get move distance
s *= 0.25
# Get new coordinates
if d != 0
dx = (d % 3 == 0 ? 1 : d % 3 == 1 ? -1 : 0)
dy = (d <= 3 ? 1 : d >= 7 ? -1 : 0)
new_x, new_y = x + dx * s, y + dy * s
else
dx = dy = 0
new_x, new_y = x, y
end
[new_x, new_y, dx, dy]
end
#--------------------------------------------------------------------------
# * Determine if Passable
# x : x-coordinate
# y : y-coordinate
# d : direction (0,1,2,3,4,6,7,8,9)
# * 0 = Determines if all directions are impassable (for jumping)
# s : steps (1..4)
# n : new coordinates as calculated by get_new_coordinates
# if not specified, they are calculated here
#--------------------------------------------------------------------------
def passable?(x, y, d, s = EVENT_DISTANCE, n = get_new_coordinates(x, y, d, s))
# Get new coordinates
new_x, new_y, dx, dy = *n
# If coordinates are outside of map: impassable
return false unless $game_map.valid?(new_x, new_y)
# If through is ON: passable
return true if @through
# Get move distance
s *= 0.25
# Standfeld berechnen
fx, fy = x.to_field, y.to_field
# Überprüfen, ob neues Feld betreten wird
cx = ((x - fx).abs < s and 0 < dx*(new_x - x))
cy = ((y - fy).abs < s and 0 < dy*(new_y - y))
if cx and cy
return false unless $game_map.passable?(fx, fy, d) and $game_map.passable?(fx + dx, fy + dy, 10 - d)
elsif cx
# Normale Überprüfung
return false unless $game_map.passable?(fx, fy, 5 + dx) and $game_map.passable?(fx + dx, fy, 5 - dx)
# Wenn Spieler zwischen 2 Feldern steht...
if y != fy
cy = fy + (y <=> fy)
# ... nebenliegendes Feld überprüfen...
return false unless $game_map.passable?(fx, cy, 5 + dx) and $game_map.passable?(fx + dx, cy, 5 - dx)
# ... sicherstellen, dass fy das obere, cy das untere Feld ist...
fy, cy = cy, fy if cy < fy
y = (y - fy) % 1
# ... oberes Feld nach unten überprüfen...
return false if y <= 0.5 and not ($game_map.passable?(fx + dx, cy, 2) and $game_map.passable?(fx + dx, fy, 8))
# ... und unteres Feld nach oben überprüfen
return false if y >= 0.5 and not ($game_map.passable?(fx + dx, fy, 8) and $game_map.passable?(fx + dx, cy, 2))
end
elsif cy
# Normale Überprüfung
return false unless $game_map.passable?(fx, fy, 5 - 3 * dy) and $game_map.passable?(fx, fy + dy, 5 + 3 * dy)
# Wenn Spieler zwischen 2 Feldern steht...
if x != fx
cx = fx + (x <=> fx)
# ... nebenliegendes Feld überprüfen...
return false unless $game_map.passable?(cx, fy, 5 - 3 * dy) and $game_map.passable?(cx, fy + dy, 5 + 3 * dy)
# ... sicherstellen, dass fx das linke, cx das rechte Feld ist...
fx, cx = cx, fx if cx < fx
x = (x - fx) % 1
# ... rechtes Feld nach links überprüfen...
return false if x <= 0.5 and not ($game_map.passable?(cx, fy + dy, 4) and $game_map.passable?(fx, fy + dy, 6))
# ... und linkes Feld nach rechts überprüfen
return false if x >= 0.5 and not ($game_map.passable?(fy, fy + dy, 6) and $game_map.passable?(cx, fy + dy, 4))
end
end
# Loop all events
for event in $game_map.events.values
next if event == self or event.through
# If through is OFF and (self is player => partner graphic as character)
# and event coordinates are consistent with move destination
if #not event.through and event.character_name != "" and
(self != $game_player or event.character_name != "") and
(event.x - new_x).abs < 1 and (event.y - new_y).abs < 1
# impassable
return false
end
end
# If self is not player, player through is OFF coordinates are consistent
# with move destination and your own graphic is the character
if self != $game_player and not $game_player.through and
@character_name != "" and ($game_player.x - new_x).abs < 1 and
($game_player.y - new_y).abs < 1
# impassable
return false
end
# passable
return true
end
#--------------------------------------------------------------------------
# * Move
# dir : direction (0,1,2,3,4,6,7,8,9)
# steps : number of steps to move (4 = 1 field)
# turn_enabled : a flag permits direction change on that spot
#--------------------------------------------------------------------------
def move(dir, steps = EVENT_DISTANCE, turn_enabled = true)
return if dir == 0
turned = false
# Turn to specified direction
if turn_enabled
turn(dir)
turned = true
end
# Calculate new coordinates
new_coords = get_new_coordinates(@x, @y, dir, steps)
# If passable and route free
if passable?(@x, @y, dir, steps, new_coords)
# Turn to specified direction
turn(dir) unless turned
# Update coordinates
@x, @y = new_coords
# Increase steps
increase_steps
# Slide if moving diagonally
elsif dir % 2 == 1 and
((m = dir % 6) == 1 and passable?(@x, @y, 4, steps, n = get_new_coordinates(@x, @y, 4, steps)) or
(m == 3 and passable?(@x, @y, 6, steps, n = get_new_coordinates(@x, @y, 6, steps))) or
(dir < 5 and passable?(@x, @y, 2, steps, n = get_new_coordinates(@x, @y, 2, steps))) or
(dir > 5 and passable?(@x, @y, 8, steps, n = get_new_coordinates(@x, @y, 8, steps))))
# Update coordinates
@x, @y = n#ew_coords
# Increase steps
increase_steps
# If impassable
else
# Determine if touch event is triggered
check_event_trigger_touch(new_coords[0], new_coords[1])
end
end
#--------------------------------------------------------------------------
# * Move Down
# turn_enabled : a flag permits direction change on that spot
# steps : number of steps to move (4 = 1 field)
#--------------------------------------------------------------------------
def move_down(turn_enabled = true, steps = EVENT_DISTANCE)
move(2, steps, turn_enabled)
end
#--------------------------------------------------------------------------
# * Move Left
# turn_enabled : a flag permits direction change on that spot
# steps : number of steps to move (4 = 1 field)
#--------------------------------------------------------------------------
def move_left(turn_enabled = true, steps = EVENT_DISTANCE)
move(4, steps, turn_enabled)
end
#--------------------------------------------------------------------------
# * Move Right
# turn_enabled : a flag permits direction change on that spot
# steps : number of steps to move (4 = 1 field)
#--------------------------------------------------------------------------
def move_right(turn_enabled = true, steps = EVENT_DISTANCE)
move(6, steps, turn_enabled)
end
#--------------------------------------------------------------------------
# * Move up
# turn_enabled : a flag permits direction change on that spot
# steps : number of steps to move (4 = 1 field)
#--------------------------------------------------------------------------
def move_up(turn_enabled = true, steps = EVENT_DISTANCE)
move(8, steps, turn_enabled)
end
#--------------------------------------------------------------------------
# * Move Lower Left
# steps : number of steps to move (4 = 1 field)
#--------------------------------------------------------------------------
def move_lower_left(steps = EVENT_DISTANCE)
move(1, steps)
end
#--------------------------------------------------------------------------
# * Move Lower Right
# steps : number of steps to move (4 = 1 field)
#--------------------------------------------------------------------------
def move_lower_right(steps = EVENT_DISTANCE)
move(3, steps)
end
#--------------------------------------------------------------------------
# * Move Upper Left
# steps : number of steps to move (4 = 1 field)
#--------------------------------------------------------------------------
def move_upper_left(steps = EVENT_DISTANCE)
move(7, steps)
end
#--------------------------------------------------------------------------
# * Move Upper Right
# steps : number of steps to move (4 = 1 field)
#--------------------------------------------------------------------------
def move_upper_right(steps = EVENT_DISTANCE)
move(9, steps)
end
#--------------------------------------------------------------------------
# * Turn
# d : direction (1,2,3,4,6,7,8,9)
#--------------------------------------------------------------------------
def turn(d)
# If no direction fix
unless @direction_fix
if d % 2 == 1
# If diagonal direction specified, replace it with good straight
# direction if the character is facing an opposite direction
if ((m = d % 6) == 1 and @direction == 6) or
(m == 3 and @direction == 4) or
(d < 5 and @direction == 8) or
(d > 5 and @direction == 2)
@direction = 10 - @direction
end
else
@direction = d
end
@stop_count = 0
end
end
#--------------------------------------------------------------------------
# * Update frame (move)
#--------------------------------------------------------------------------
def update_move
# Convert map coordinates from map move speed into move distance
distance = 2 ** @move_speed
# Apply cost for diagonal movement
if DIAGONAL_COST and @x * 128 != @real_x and @y * 128 != @real_y
distance = (distance / DIAGONAL_COST).round
end
# If logical coordinates are further down than real coordinates
if @y * 128 > @real_y
# Move down
@real_y = [@real_y + distance, @y * 128].min
end
# If logical coordinates are more to the left than real coordinates
if @x * 128 < @real_x
# Move left
@real_x = [@real_x - distance, @x * 128].max
end
# If logical coordinates are more to the right than real coordinates
if @x * 128 > @real_x
# Move right
@real_x = [@real_x + distance, @x * 128].min
end
# If logical coordinates are further up than real coordinates
if @y * 128 < @real_y
# Move up
@real_y = [@real_y - distance, @y * 128].max
end
# If move animation is ON
if @walk_anime
# Increase animation count by 1.5
@anime_count += 1.5
# If move animation is OFF, and stop animation is ON
elsif @step_anime
# Increase animation count by 1
@anime_count += 1
end
end
end
class ::Game_Event
#--------------------------------------------------------------------------
# * Touch Event Starting Determinant
#--------------------------------------------------------------------------
def check_event_trigger_touch(x, y)
# If event is running
if $game_system.map_interpreter.running?
return
end
# If starting determinant other than jumping is front event and
# trigger is [touch from event] and consistent with player coordinates
if @trigger == 2 and not over_trigger? and not jumping? and
($game_player.x - @x).abs <= 0.5 and ($game_player.y - @y).abs <= 0.5
start
end
end
#--------------------------------------------------------------------------
# * Automatic Event Starting Determinant
#--------------------------------------------------------------------------
def check_event_trigger_auto
# If starting determinant other than jumping is same position event and
# trigger is [touch from event] and consistent with player coordinates
if @trigger == 2 and over_trigger? and not jumping? and
($game_player.x - @x).abs <= 0.5 and ($game_player.y - @y).abs <= 0.5
start
# If trigger is [auto run]
elsif @trigger == 3
start
end
end
end
# Schüsse/Treffer und Achtrichtungs- und Pixelmovement
class ::Game_Player
def move(dir, steps = PLAYER_DISTANCE, turn_enabled = true)
super
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# Remember whether or not moving in local variables
last_moving = moving?
# Richtung fixieren
if STRAFE_KEY
if Input.press?(STRAFE_KEY)
if @pre_fix == nil
@pre_fix = @direction_fix
@direction_fix = true
end
elsif @pre_fix != nil
@direction_fix = @pre_fix
@pre_fix = nil
end
end
# If moving, event running, move route forcing, and message window
# display are all not occurring
if not (moving? or $game_system.map_interpreter.running? or
@move_route_forcing or $game_temp.message_window_showing)
# Move player in the direction the directional button is being pressed
move(PLAYER_8_DIR ? Input.dir8 : Input.dir4)
end
# Remember coordinates in local variables
last_real_x = @real_x
last_real_y = @real_y
super
# If character moves down and is positioned lower than the center
# of the screen
if @real_y > last_real_y and @real_y - $game_map.display_y > CENTER_Y
# Scroll map down
$game_map.scroll_down(@real_y - last_real_y)
end
# If character moves left and is positioned more let on-screen than
# center
if @real_x < last_real_x and @real_x - $game_map.display_x < CENTER_X
# Scroll map left
$game_map.scroll_left(last_real_x - @real_x)
end
# If character moves right and is positioned more right on-screen than
# center
if @real_x > last_real_x and @real_x - $game_map.display_x > CENTER_X
# Scroll map right
$game_map.scroll_right(@real_x - last_real_x)
end
# If character moves up and is positioned higher than the center
# of the screen
if @real_y < last_real_y and @real_y - $game_map.display_y < CENTER_Y
# Scroll map up
$game_map.scroll_up(last_real_y - @real_y)
end
# If not moving
unless moving?
# If player was moving last time
if last_moving
# Event determinant is via touch of same position event
result = check_event_trigger_here([1,2])
# If event which started does not exist
if result == false
# Disregard if debug mode is ON and ctrl key was pressed
unless $DEBUG and Input.press?(Input::CTRL)
# Encounter countdown
if @encounter_count > 0
@encounter_count -= 1
end
end
end
end
# If C button was pressed
if Input.trigger?(Input::C)
# Same position and front event determinant
check_event_trigger_here([0])
check_event_trigger_there([0,1,2])
end
end
end
#--------------------------------------------------------------------------
# * Passable Determinants
# x : x-coordinate
# y : y-coordinate
# d : direction (0,2,4,6,8)
# * 0 = Determines if all directions are impassable (for jumping)
# s : steps (1..4)
#--------------------------------------------------------------------------
def passable?(x, y, d, s = 4, n = get_new_coordinates(x, y, d, s))
# If coordinates are outside of map: impassable
return false unless $game_map.valid?(n[0], n[1])
# If debug mode is ON and ctrl key was pressed: passable
return true if $DEBUG and Input.press?(Input::CTRL)
super
end
#--------------------------------------------------------------------------
# * Same Position Starting Determinant
#--------------------------------------------------------------------------
def check_event_trigger_here(triggers)
# If no event is running
unless $game_system.map_interpreter.running?
# All event loops
for event in $game_map.events.values
# If triggers are consistent, starting determinant is same position event
# (other than jumping) and event coordinates are consistent
if event.over_trigger? and triggers.include?(event.trigger) and
(not event.jumping?) and (event.x - @x).abs <= 0.5 and (event.y - @y).abs <= 0.5
event.start
return true
end
end
end
return false
end
#--------------------------------------------------------------------------
# * Front Envent Starting Determinant
#--------------------------------------------------------------------------
def check_event_trigger_there(triggers)
# If no event is running
unless $game_system.map_interpreter.running?
# Calculate front event coordinates
new_x = @x + (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
new_y = @y + (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
# All event loops
for event in $game_map.events.values
# If triggers are consistent, starting determinant is front event
# (other than jumping) and event coordinates are consistent
if not event.over_trigger? and triggers.include?(event.trigger) and
not event.jumping? and (event.x - new_x).abs <= 0.5 and (event.y - new_y).abs <= 0.5
event.start
return true
end
end
# If front tile is a counter
if $game_map.counter?(new_x, new_y)
# Calculate 1 tile inside coordinates
new_x += (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
new_y += (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
# All event loops
for event in $game_map.events.values
# If triggers are consistent, starting determinant is front event
# (other than jumping) and event coordinates are consistent
if not event.over_trigger? and triggers.include?(event.trigger) and
not event.jumping? and (event.x - new_x).abs <= 0.5 and (event.y - new_y).abs <= 0.5
event.start
return true
end
end
end
end
return false
end
#--------------------------------------------------------------------------
# * Touch Event Starting Determinant
#--------------------------------------------------------------------------
def check_event_trigger_touch(x, y)
# If no event is running
unless $game_system.map_interpreter.running?
# All event loops
for event in $game_map.events.values
# If triggers are consistent, starting determinant is front event
# (other than jumping) and event coordinates are consistent
if not event.over_trigger? and not event.jumping? and
[1,2].include?(event.trigger) and (event.x - x).abs <= 0.5 and (event.y - y).abs <= 0.5
event.start
return true
end
end
end
return false
end
end
class ::Game_Map
alias :old_passable? :passable?
#--------------------------------------------------------------------------
# * Determine if Passable
# x : x-coordinate
# y : y-coordinate
# d : direction (0,...,10)
# * 0,10 = determine if all directions are impassable
# self_event : Self (If event is determined passable)
#--------------------------------------------------------------------------
def passable?(x, y, d, self_event = nil)
# Handle diagonal passability
if d % 2 == 1
# Calculate temporary movement direction indicators
dx, dy = d % 3 == 1 ? -1 : 1, 6 <=> d
# Get new position
new_x, new_y = x + dx, y + dy
# Get movement directions
dx, dy = 5 + dx, 5 + 3 * dy
# Calculate passability
passable?(x, y, dx, self_event) and passable?(x, new_y, dx, self_event) and
passable?(x, y, dy, self_event) and passable?(new_x, y, dy, self_event)
else
old_passable(x, y, d, self_event)
end
end
end
end
__________________
"So, und jetzt Schluss mit dem Lamentieren - lasst uns etwas Kunst machen!!!" - GS_Raphael
Geändert von derula (15.10.2009 um 18:49 Uhr).
|