|
3 | 3 | #include <scratchcpp/input.h> |
4 | 4 | #include <scratchcpp/field.h> |
5 | 5 | #include <scratchcpp/sprite.h> |
| 6 | +#include <scratchcpp/costume.h> |
| 7 | +#include <scratchcpp/scratchconfiguration.h> |
6 | 8 | #include <enginemock.h> |
7 | 9 | #include <randomgeneratormock.h> |
8 | 10 | #include <clockmock.h> |
| 11 | +#include <imageformatfactorymock.h> |
| 12 | +#include <imageformatmock.h> |
9 | 13 |
|
10 | 14 | #include "../common.h" |
11 | 15 | #include "blocks/motionblocks.h" |
@@ -115,6 +119,7 @@ TEST_F(MotionBlocksTest, RegisterBlocks) |
115 | 119 | EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "motion_setx", &MotionBlocks::compileSetX)); |
116 | 120 | EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "motion_changeyby", &MotionBlocks::compileChangeYBy)); |
117 | 121 | EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "motion_sety", &MotionBlocks::compileSetY)); |
| 122 | + EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "motion_ifonedgebounce", &MotionBlocks::compileIfOnEdgeBounce)); |
118 | 123 | EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "motion_setrotationstyle", &MotionBlocks::compileSetRotationStyle)); |
119 | 124 | EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "motion_xposition", &MotionBlocks::compileXPosition)); |
120 | 125 | EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "motion_yposition", &MotionBlocks::compileYPosition)); |
@@ -1085,6 +1090,142 @@ TEST_F(MotionBlocksTest, SetYImpl) |
1085 | 1090 | ASSERT_EQ(sprite.y(), 189.42); |
1086 | 1091 | } |
1087 | 1092 |
|
| 1093 | +TEST_F(MotionBlocksTest, IfOnEdgeBounce) |
| 1094 | +{ |
| 1095 | + Compiler compiler(&m_engineMock); |
| 1096 | + |
| 1097 | + auto block = std::make_shared<Block>("a", "motion_ifonedgebounce"); |
| 1098 | + |
| 1099 | + EXPECT_CALL(m_engineMock, functionIndex(&MotionBlocks::ifOnEdgeBounce)).WillOnce(Return(0)); |
| 1100 | + |
| 1101 | + compiler.init(); |
| 1102 | + compiler.setBlock(block); |
| 1103 | + MotionBlocks::compileIfOnEdgeBounce(&compiler); |
| 1104 | + compiler.end(); |
| 1105 | + |
| 1106 | + ASSERT_EQ(compiler.bytecode(), std::vector<unsigned int>({ vm::OP_START, vm::OP_EXEC, 0, vm::OP_HALT })); |
| 1107 | + ASSERT_TRUE(compiler.constValues().empty()); |
| 1108 | +} |
| 1109 | + |
| 1110 | +TEST_F(MotionBlocksTest, IfOnEdgeBounceImpl) |
| 1111 | +{ |
| 1112 | + static unsigned int bytecode[] = { vm::OP_START, vm::OP_EXEC, 0, vm::OP_HALT }; |
| 1113 | + static BlockFunc functions[] = { &MotionBlocks::ifOnEdgeBounce }; |
| 1114 | + |
| 1115 | + auto imageFormatFactory = std::make_shared<ImageFormatFactoryMock>(); |
| 1116 | + auto imageFormat = std::make_shared<ImageFormatMock>(); |
| 1117 | + |
| 1118 | + ScratchConfiguration::registerImageFormat("test", imageFormatFactory); |
| 1119 | + EXPECT_CALL(*imageFormatFactory, createInstance()).WillOnce(Return(imageFormat)); |
| 1120 | + EXPECT_CALL(*imageFormat, width()).WillOnce(Return(0)); |
| 1121 | + EXPECT_CALL(*imageFormat, height()).WillOnce(Return(0)); |
| 1122 | + auto costume = std::make_shared<Costume>("costume1", "a", "test"); |
| 1123 | + |
| 1124 | + Sprite sprite; |
| 1125 | + sprite.addCostume(costume); |
| 1126 | + sprite.setCostumeIndex(0); |
| 1127 | + |
| 1128 | + static char data[5] = "abcd"; |
| 1129 | + EXPECT_CALL(*imageFormat, setData(5, data)); |
| 1130 | + EXPECT_CALL(*imageFormat, width()).WillOnce(Return(4)); |
| 1131 | + EXPECT_CALL(*imageFormat, height()).WillOnce(Return(3)); |
| 1132 | + |
| 1133 | + EXPECT_CALL(*imageFormat, colorAt(0, 0, 1)).WillOnce(Return(rgba(0, 0, 0, 0))); |
| 1134 | + EXPECT_CALL(*imageFormat, colorAt(1, 0, 1)).WillOnce(Return(rgba(0, 0, 0, 0))); |
| 1135 | + EXPECT_CALL(*imageFormat, colorAt(2, 0, 1)).WillOnce(Return(rgba(0, 0, 0, 255))); |
| 1136 | + EXPECT_CALL(*imageFormat, colorAt(3, 0, 1)).WillOnce(Return(rgba(0, 0, 0, 0))); |
| 1137 | + |
| 1138 | + EXPECT_CALL(*imageFormat, colorAt(0, 1, 1)).WillOnce(Return(rgba(0, 0, 0, 0))); |
| 1139 | + EXPECT_CALL(*imageFormat, colorAt(1, 1, 1)).WillOnce(Return(rgba(0, 0, 0, 255))); |
| 1140 | + EXPECT_CALL(*imageFormat, colorAt(2, 1, 1)).WillOnce(Return(rgba(0, 0, 0, 0))); |
| 1141 | + EXPECT_CALL(*imageFormat, colorAt(3, 1, 1)).WillOnce(Return(rgba(0, 0, 0, 255))); |
| 1142 | + |
| 1143 | + EXPECT_CALL(*imageFormat, colorAt(0, 2, 1)).WillOnce(Return(rgba(0, 0, 0, 255))); |
| 1144 | + EXPECT_CALL(*imageFormat, colorAt(1, 2, 1)).WillOnce(Return(rgba(0, 0, 0, 0))); |
| 1145 | + EXPECT_CALL(*imageFormat, colorAt(2, 2, 1)).WillOnce(Return(rgba(0, 0, 0, 0))); |
| 1146 | + EXPECT_CALL(*imageFormat, colorAt(3, 2, 1)).WillOnce(Return(rgba(0, 0, 0, 0))); |
| 1147 | + costume->setData(5, data); |
| 1148 | + |
| 1149 | + sprite.setEngine(&m_engineMock); |
| 1150 | + |
| 1151 | + VirtualMachine vm(&sprite, &m_engineMock, nullptr); |
| 1152 | + vm.setBytecode(bytecode); |
| 1153 | + vm.setFunctions(functions); |
| 1154 | + |
| 1155 | + EXPECT_CALL(*imageFormat, width()).Times(9).WillRepeatedly(Return(4)); |
| 1156 | + EXPECT_CALL(*imageFormat, height()).Times(9).WillRepeatedly(Return(3)); |
| 1157 | + EXPECT_CALL(m_engineMock, stageWidth()).Times(9).WillRepeatedly(Return(480)); |
| 1158 | + EXPECT_CALL(m_engineMock, stageHeight()).Times(9).WillRepeatedly(Return(360)); |
| 1159 | + |
| 1160 | + // No edge |
| 1161 | + EXPECT_CALL(m_engineMock, requestRedraw()).Times(3); |
| 1162 | + EXPECT_CALL(m_engineMock, spriteFencingEnabled()).Times(2).WillRepeatedly(Return(false)); |
| 1163 | + sprite.setX(100); |
| 1164 | + sprite.setY(60); |
| 1165 | + sprite.setDirection(-45); |
| 1166 | + vm.run(); |
| 1167 | + |
| 1168 | + ASSERT_EQ(vm.registerCount(), 0); |
| 1169 | + ASSERT_EQ(sprite.x(), 100); |
| 1170 | + ASSERT_EQ(sprite.y(), 60); |
| 1171 | + ASSERT_EQ(sprite.direction(), -45); |
| 1172 | + |
| 1173 | + // Left edge |
| 1174 | + EXPECT_CALL(m_engineMock, requestRedraw()).Times(5); |
| 1175 | + EXPECT_CALL(m_engineMock, spriteFencingEnabled()).Times(4).WillRepeatedly(Return(false)); |
| 1176 | + sprite.setX(-240); |
| 1177 | + sprite.setY(60); |
| 1178 | + vm.reset(); |
| 1179 | + vm.run(); |
| 1180 | + |
| 1181 | + ASSERT_EQ(vm.registerCount(), 0); |
| 1182 | + ASSERT_EQ(std::round(sprite.x() * 100) / 100, -238.23); |
| 1183 | + ASSERT_EQ(sprite.y(), 60); |
| 1184 | + ASSERT_EQ(std::round(sprite.direction() * 100) / 100, 45); |
| 1185 | + |
| 1186 | + // Top edge |
| 1187 | + EXPECT_CALL(m_engineMock, requestRedraw()).Times(6); |
| 1188 | + EXPECT_CALL(m_engineMock, spriteFencingEnabled()).Times(4).WillRepeatedly(Return(false)); |
| 1189 | + sprite.setX(100); |
| 1190 | + sprite.setY(180); |
| 1191 | + sprite.setDirection(45); |
| 1192 | + vm.reset(); |
| 1193 | + vm.run(); |
| 1194 | + |
| 1195 | + ASSERT_EQ(vm.registerCount(), 0); |
| 1196 | + ASSERT_EQ(sprite.x(), 100); |
| 1197 | + ASSERT_EQ(std::round(sprite.y() * 100) / 100, 178.23); |
| 1198 | + ASSERT_EQ(sprite.direction(), 135); |
| 1199 | + |
| 1200 | + // Right edge |
| 1201 | + EXPECT_CALL(m_engineMock, requestRedraw()).Times(5); |
| 1202 | + EXPECT_CALL(m_engineMock, spriteFencingEnabled()).Times(4).WillRepeatedly(Return(false)); |
| 1203 | + sprite.setX(240); |
| 1204 | + sprite.setY(60); |
| 1205 | + vm.reset(); |
| 1206 | + vm.run(); |
| 1207 | + |
| 1208 | + ASSERT_EQ(vm.registerCount(), 0); |
| 1209 | + ASSERT_EQ(std::round(sprite.x() * 100) / 100, 238.23); |
| 1210 | + ASSERT_EQ(sprite.y(), 60); |
| 1211 | + ASSERT_EQ(sprite.direction(), -135); |
| 1212 | + |
| 1213 | + // Bottom edge |
| 1214 | + EXPECT_CALL(m_engineMock, requestRedraw()).Times(5); |
| 1215 | + EXPECT_CALL(m_engineMock, spriteFencingEnabled()).Times(4).WillRepeatedly(Return(false)); |
| 1216 | + sprite.setX(-100); |
| 1217 | + sprite.setY(-180); |
| 1218 | + vm.reset(); |
| 1219 | + vm.run(); |
| 1220 | + |
| 1221 | + ASSERT_EQ(vm.registerCount(), 0); |
| 1222 | + ASSERT_EQ(sprite.x(), -100); |
| 1223 | + ASSERT_EQ(std::round(sprite.y() * 100) / 100, -178.23); |
| 1224 | + ASSERT_EQ(std::round(sprite.direction() * 100) / 100, -45); |
| 1225 | + |
| 1226 | + ScratchConfiguration::removeImageFormat("test"); |
| 1227 | +} |
| 1228 | + |
1088 | 1229 | TEST_F(MotionBlocksTest, SetRotationStyle) |
1089 | 1230 | { |
1090 | 1231 | Compiler compiler(&m_engineMock); |
|
0 commit comments