一个例子
角色利用碰撞捡取物品,直接画在hud上做的背包ui,可拖拽.
有点需要注意,获取的鼠标位置是以viewport大小为基准,游戏中的hud坐标系(0,0)是以非黑边处第一个像素点,如果满viewport显示,则与鼠标坐标系一致。
#pragma once
#include "GameFramework/HUD.h"
#include "MyHUD.generated.h"
/**
*
*/
struct Message
{
FString message;
float time;
UTexture2D *pTex;
FColor color;
Message()
{
time = 5.f;
color = FColor::White;
}
Message(FString iMessage, float iTime, FColor iColor, UTexture2D *tTex)
{
message = iMessage;
time = iTime;
color = iColor;
pTex = tTex;
}
};
struct Icon
{
FString name;
UTexture2D *tex;
Icon()
{
name = TEXT("unknown");
tex = 0;
}
Icon(FString &iName, UTexture2D *iTex)
{
name = iName;
tex = iTex;
}
};
struct Widget
{
Icon icon;
FVector2D pos, size;
Widget(Icon iIcon)
{
icon = iIcon;
}
bool hit(FVector2D p);
float left() { return pos.X; }
float right() { return pos.X + size.X; }
float top() { return pos.Y; }
float bottom() { return pos.Y + size.Y; }
};
UCLASS()
class BASICPROJ_API AMyHUD : public AHUD
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, Category = HUDFont)
UFont *hudFont;
TArray<Message> messages;
TArray<Widget> widgets;
public:
void addMessage(Message msg);
void DrawHealthBar();
void DrawWidgets();
void ClearWidgets();
void AddWidget(Widget widget);
void MouseClicked();
void MouseMoved();
private:
virtual void DrawHUD() override;
private:
Widget *holdWidget;
};
void AMyHUD::DrawHUD()
{
Super::DrawHUD();
DrawHealthBar();
for (int i = messages.Num() - 1; i >= 0; --i)
{
float outputWidth, ouputHeight, pad = 10.f;
GetTextSize(messages[i].message, outputWidth, ouputHeight, hudFont, 1.f);
float messageH = ouputHeight + 2.f * pad;
float x = 0.f, y = i * messageH;
DrawTexture(messages[i].pTex, x, y, messageH, messageH, 0, 0, 1, 1);
DrawRect(FLinearColor::Blue, x, y, outputWidth, messageH);
DrawText(messages[i].message, messages[i].color, x + pad, y + pad, hudFont);
messages[i].time -= GetWorld()->GetDeltaSeconds();
if (messages[i].time < 0)
{
messages.RemoveAt(i);
}
}
DrawWidgets();
}
void AMyHUD::addMessage(Message msg)
{
messages.Add(msg);
}
void AMyHUD::DrawHealthBar()
{
AAvatar *avatar = Cast<AAvatar>(UGameplayStatics::GetPlayerPawn(GetWorld(), 0));
float barWidth = 200, barHeight = 50, barPad = 12, barMargin = 50;
float percHp = avatar->Hp / avatar->MaxHp;
DrawRect(FLinearColor(0, 0, 0, 1), Canvas->SizeX - barWidth -
barPad - barMargin, Canvas->SizeY - barHeight - barPad -
barMargin, barWidth + 2 * barPad, barHeight + 2 * barPad);
DrawRect(FLinearColor(1 - percHp, percHp, 0, 1), Canvas->SizeX
- barWidth - barMargin, Canvas->SizeY - barHeight - barMargin,
barWidth*percHp, barHeight);
}
void AMyHUD::DrawWidgets()
{
for (int i = 0; i < widgets.Num(); ++i)
{
DrawTexture(widgets[i].icon.tex, widgets[i].pos.X, widgets[i].pos.Y, widgets[i].size.X,
widgets[i].size.Y, 0, 0, 1, 1);
DrawText(widgets[i].icon.name, FLinearColor::Yellow, widgets[i].pos.X, widgets[i].pos.Y, hudFont, .6f, false);
}
}
void AMyHUD::AddWidget(Widget widget)
{
FVector2D start(0, 0), pad(12, 12);
widget.size = FVector2D(100, 100);
widget.pos = start;
for (int i = 0; i < widgets.Num(); ++i)
{
widget.pos.X += widget.size.X + pad.X;
if (widget.pos.X + widget.size.X > 800)
{
widget.pos.X = start.X;
widget.pos.Y += widget.size.Y + pad.Y;
}
}
widgets.Add(widget);
}
void AMyHUD::ClearWidgets()
{
for (int i = widgets.Num() - 1; i >= 0; --i)
{
widgets.RemoveAt(i);
}
}
void AMyHUD::MouseClicked()
{
static FVector2D mouse;
APlayerController *pController = GetWorld()->GetFirstPlayerController();
pController->GetMousePosition(mouse.X, mouse.Y);
for (int i = 0; i < widgets.Num(); ++i)
{
if (widgets[i].hit(mouse))
{
holdWidget = &widgets[i];
return ;
}
}
}
void AMyHUD::MouseMoved()
{
static FVector2D lastMouse;
FVector2D thisMouse, dMouse;
APlayerController *pController = GetWorld()->GetFirstPlayerController();
pController->GetMousePosition(thisMouse.X, thisMouse.Y);
dMouse = thisMouse - lastMouse;
float time = pController->GetInputKeyTimeDown(EKeys::LeftMouseButton);
if (time > 0.f && holdWidget)
{
holdWidget->pos.X += dMouse.X;
holdWidget->pos.Y += dMouse.Y;
}
lastMouse = thisMouse;
}
bool Widget::hit(FVector2D p)
{
int a = left();
int b = right();
int c = top();
int d = bottom();
GEngine->ClearOnScreenDebugMessages();
FString textt = FString::Printf(TEXT("mousex=%f, mousey=%f \nLEFT=%f right = %f top = %f bo= %f"), p.X, p.Y, left(), right(), top(), bottom());
GEngine->AddOnScreenDebugMessage(-1, 100.f, FColor::Yellow, textt);
return p.X > a && p.X <b && p.Y > c && p.Y < d;
}
// Called to bind functionality to input
void AAvatar::SetupPlayerInputComponent(class UInputComponent* InputComponent)
{
check(InputComponent);
Super::SetupPlayerInputComponent(InputComponent);
InputComponent->BindAxis("Forward", this, &AAvatar::MoveForward);
InputComponent->BindAxis("Strafe", this, &AAvatar::MoveRight);
InputComponent->BindAxis("left", this, &AAvatar::MoveRight);
InputComponent->BindAxis("back", this, &AAvatar::MoveForward);
InputComponent->BindAxis("Yaw", this, &AAvatar::Yaw);
InputComponent->BindAxis("Pitch", this, &AAvatar::Pitch);
InputComponent->BindAction("Bag",IE_Pressed, this, &AAvatar::OpenBag);
InputComponent->BindAction("MouseClickedLMB", IE_Pressed, this, &AAvatar::MouseClicked);
}
void AAvatar::MoveForward( float fAmount )
{
if (Controller && fAmount)
{
FVector fVec = GetActorForwardVector();
AddMovementInput(fVec, fAmount);
}
}
void AAvatar::MoveRight( float fAmount )
{
if (Controller && fAmount)
{
FVector right = GetActorRightVector();
AddMovementInput(right, fAmount);
}
}
void AAvatar::Yaw(float f)
{
if (InventoryShowing)
{
APlayerController *pController = GetWorld()->GetFirstPlayerController();
AMyHUD *hud = Cast<AMyHUD>(pController->GetHUD());
hud->MouseMoved();
return;
}
AddControllerYawInput(200.f * f * GetWorld()->GetDeltaSeconds());
}
void AAvatar::Pitch(float f)
{
if (InventoryShowing)
{
APlayerController *pController = GetWorld()->GetFirstPlayerController();
AMyHUD *hud = Cast<AMyHUD>(pController->GetHUD());
hud->MouseMoved();
return;
}
AddControllerPitchInput(200.f * -f * GetWorld()->GetDeltaSeconds());
}
void AAvatar::OpenBag()
{
APlayerController *pController = GetWorld()->GetFirstPlayerController();
AMyHUD *hud = Cast<AMyHUD>(pController->GetHUD());
if (InventoryShowing)
{
hud->ClearWidgets();
InventoryShowing = false;
pController->bShowMouseCursor = false;
return;
}
InventoryShowing = true;
pController->bShowMouseCursor = true;
for (TMap<FString, BagItem>::TIterator it = BackPack.CreateIterator(); it; ++it)
{
FString fs = it->Key + FString::Printf(TEXT("X %d"), it->Value.iNum);
UTexture2D *tex;
tex = it->Value.pICon;
hud->AddWidget(Widget(Icon(fs, tex)));
}
}
void AAvatar::PickUp(APickItem *item)
{
if (BackPack.Find(item->Name))
{
BackPack[item->Name].iNum += item->Quantity;
}
else
{
BagItem bitem;
bitem.iNum = item->Quantity;
bitem.pICon = item->Icon;
BackPack.Add(item->Name, bitem);
}
}
void AAvatar ::MouseClicked()
{
APlayerController *pController = GetWorld()->GetFirstPlayerController();
AMyHUD *hud = Cast<AMyHUD>(pController->GetHUD());
hud->MouseClicked();
}